目录
一、创建一个简单的Vue前端项目(可忽略)
二、使用Flask部署上述Vue打包后的dist(前后端未分离)
三、使用Django部署上述Vue打包后的dist(前后端未分离)
四、容器化部署章节二和章节三输出的项目(前后端未分离)
4.1 乌班图下的Docker安装
4.2 乌班图下 使用Docker部署章节二的Flask项目
4.3 乌班图下 使用Docker部署章节三的Django项目
4.4 镜像迁移(项目迁移)
五、前后端分离下的容器化项目部署
5.1 nginx的安装
5.2 nginx的配置与载入vue打包后的dist
5.3 后端实现
5.4 容器化部署
本章节内容为小白向,简述如何创建一个最小化是Vue前端项目并实现项目打包。
准备工具:node.js
在指定目录下新建一个Vue项目,根据执行提示,项目名命名为demo。
npm init vue@latest
这个命令会安装和执行 create-vue,它是 Vue 提供的官方脚手架工具。
根据系统提示运行相应的命令
cd demo
npm install
npm run dev
就可以运行Vue的最小Demo了,运行效果:
现在停止运行服务。
我们有一个小小的需求(模拟正式项目中的前后端通信):就是新建一个http接口访问的轮询,要求每5秒钟请求一次后端/api/name接口,并将返回的结果展示到前端页面中。
安装axios
npm install axios
并且在Vue组件中导入它,以下提供了关键代码(添加在了HelloWorld.vue中):
执行本地编译脚本:
npm run build
本地的前端项目目录下就会生成一个dist文件夹,文件夹内包含前端静态页面及相关的静态资源
这也是小型项目传统的部署方式
首先看目录结构:
其次是app.py的源码:
from flask import Flask, render_template
app = Flask(__name__, static_folder='./dist', template_folder='./dist', static_url_path="")
# 提供Vue.js项目的index.html
@app.route('/')
def index():
return render_template('index.html', name='index')
# 前端轮询接口
@app.route('/api/name')
def get_name():
return "帅大爷"
if __name__ == '__main__':
app.run()
就已经实现章节一所需要的功能了,实现效果如下图,每个5秒钟变更一次DOM内容
正式项目请使用gunicorn等工具部署服务。
该功能建议在小型Demo 开发环境下部署使用,生产环境不建议用该方式。
使用以下脚本在特定目录下新建一个django项目(需要配置环境变量)
django-admin startproject demo
执行
python manage.py runserver
就可以启动django的最小demo了,但是我们如何实现章节一的需求呢?
后端目录结构:
目录解释说明:
assets是vue打包后dist中的assets拷贝而来
static下的dist也是vue打包后的dist
在views.py中,配置轮询请求接口,代码如下:
from django.http import HttpResponse
# 配置自定义接口
def get_name(request):
return HttpResponse("帅大爷")
在urls.py中,配置路由,代码如下:
from django.urls import path
# 自定义路径引用
from app_demo import views
from django.views.generic.base import TemplateView
urlpatterns = [
path('api/name/', views.get_name),
path('', TemplateView.as_view(template_name='index.html'))
]
重头戏来了,需要在setting.py中配置静态资源访问地址:
提供部分需要修改配置的代码如下:
# 修改前端渲染页面所在的路径,也就是index.html所以在的路径
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
# 修改dirs配置,使vue打包好的文件可以被访问
'DIRS': [os.path.join(BASE_DIR, 'static/dist')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
# ...
# 间隔若干行代码
# ...
# 配置静态资源访问地址,使前端assets能够访问到该路径下(js、css)
STATIC_URL = '/assets/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static/dist/assets'),
]
启动Django服务便可以看到和章节二末尾一样的展示效果。
正式项目请使用gunicorn等工具部署服务。
该功能建议在小型Demo 开发环境下部署使用,生产环境不建议用该方式。
更新系统软件包列表
sudo apt update
安装必要的依赖项
sudo apt install -y apt-transport-https ca-certificates curl software-properties-common
添加Docker官方GPG密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
添加Docker APT软件包库
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list
更新软件包列表
sudo apt update
安装Docker引擎
sudo apt install -y docker-ce docker-ce-cli containerd.io
安装Docker compose
sudo apt install docker-compose
启动Docker服务
sudo service docker start
验证Docker安装
docker --version
docker-compose -v
在Linux操作系统中,找到项目目录,在项目目录下新建Dockerfile文件,如下所示:
# 设置基础镜像,这里使用 Python 3.10
FROM python:3.10
# 设置工作目录
WORKDIR /app
# 复制项目代码到容器中的 /app 目录
COPY . /app
# 安装项目依赖
RUN pip install flask -i https://pypi.tuna.tsinghua.edu.cn/simple
# 设置环境变量
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
# 启动 Flask 应用
CMD ["flask", "run"]
同样地,在目录下新建docker-compose.yml文件,如下所示:
version: '3'
services:
web:
# 指定 Dockerfile 的位置
build:
context: .
dockerfile: Dockerfile
# 映射宿主机的端口到容器的 5000 端口
ports:
- "5000:5000"
# 设置环境变量
environment:
FLASK_APP: app.py
FLASK_RUN_HOST: 0.0.0.0
构建镜像并启动容器:
docker-compose up --build
停止
docker-compose down
具体操作如4.2章节一般,没有什么太大的变化,下面分别是Dockerfile和docker-compose.yml关键文件的内容。
Dockerfile:
# 设置基础镜像,这里使用 Python 3.10
FROM python:3.10
# 设置工作目录
WORKDIR /app
# 复制项目代码到容器中的 /app 目录
COPY . /app
# 安装项目依赖
RUN pip install Django -i https://pypi.tuna.tsinghua.edu.cn/simple
# 设置环境变量
ENV DJANGO_SETTINGS_MODULE=demo.settings
ENV PYTHONUNBUFFERED=1
# 运行 Django 应用
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]
docker-compose.yml
version: '3'
services:
web:
# 指定 Dockerfile 的位置
build:
context: .
dockerfile: Dockerfile
# 映射宿主机的端口到容器的 8000 端口
ports:
- "8000:8000"
# 设置环境变量,可选
environment:
- DJANGO_SETTINGS_MODULE=demo.settings
其余操作与4.2章节保持一致,不再赘述。
将docker镜像导出为tar包:
docker save -o project_image.tar project_image:tag
其中,project_image
是你的镜像名称,tag
是你的镜像标签。
在另一台机器上导入tar包:
docker load -i project_image.tar
启动它: (参数-d 表示后台运行)
docker-compose up -d
假定我们现在有一个不含前端的Flask服务(前后端完全分离),Flask只提供http请求,不提供页面渲染。这里的项目代码和章节二中还是略有不同的,但是实现的功能需求一致,依旧为给前端测试页面每隔5秒动态请求,在DOM上新增数据填充。
乌班图下,更新软件包:
sudo apt update
输入以下命令来安装Nginx
sudo apt install nginx
启动Nginx
service nginx start
查看nginx运行状态
service nginx status
当看到
* nginx is running
显示的时候说明nginx安装成功。也可以使用源码编译安装nginx,具体操请搜索引擎搜索。
安装好nginx后,需要修改nginx的配置文件,使nginx能够找到dist包的位置
需要对 /etc/nginx/nginx.conf做出如下修改
在该文件的http配置项内,加上一个server配置:
server {
listen 5555; # 监听端口
server_name 127.0.0.1; # 替换为您的域名或服务器IP地址
location / {
root /mnt/d/linux/vue_web/dist; # 指向vue的dist目录的路径
index index.html;
try_files $uri $uri/ /index.html;
}
location /api/{
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
上述功能就是将前端请求的带有/api的接口转发到5000端口上的Flask服务上去。
如题:前端请求了http://127.0.0.1:5555/api/name会转发到http://127.0.0.1:5000/api/name上去。
停止服务并变更config文件,执行下列命令:
service nginx stop
nginx -c /etc/nginx/nginx.conf
此时,重启下nginx
sudo nginx -s reload
就可以看到前端展示的页面(访问 http://127.0.0.1:5000/):
静态页面资源已经加载出来了,但是没有请求到数据。下一章节我们将启动后端服务,呈现完整功能。
app.py代码(去除了template渲染前端):
from flask import Flask
app = Flask(__name__)
# 前端轮询接口
@app.route('/api/name')
def get_name():
return "帅大爷"
if __name__ == '__main__':
app.run()
特别提示:就上述nginx配置来看,该后端需要部署在本地机器上(映射端口127.0.0.1)跨机器需要修改ip配置。
如果使用window系统下的WSL 子系统时,该后端也必须在Linux环境下启动。
此时:后端的数据就会通过接口源源不断的请求到页面了:
容器化部署是为了迁移部署方便,可以参考4.2章的内容进行尝试。
交付的时候需要前后端对其请求接口契约,对其接口请求协议和参数,前端nginx和dist打包成一个docker容器,后端Flask/Django打包成一个docker容器。
不是很困难,有时间再更新吧,未完待续 ...