环境准备
centos7.5 + python3.9 + mysql5.7.20 + django3.2 + django restframework + virtualenv + nginx + http/https + vue + uwsgi + supervirsor + nodejs
django+vue前后端分离项目的部署,整体来说,还是相对比较麻烦,尤其是再配置上支持https的ssl证书的操作,更是有点麻烦。
这里我们先来配置不带ssl证书的部署,完事能跑通了之后,再加上ssl证书配置。
环境准备嘛,就是一顿安装就完了,我这里是基于centos7.5的安装:
- Python解释器:
- MySQL:
- nodejs:
- nginx:
- supervisor:
我现在,上述这些环境都已准备好,开干!
部署流程
先来演示不需要配置ssl证书的。
注意我后续操作所在的目录!!!!
另外,centos内置python2.7,而我同时装了python3.6和python3.9,所以,本篇调用python相关的命令,我会使用python3.9和pip3.9,以示区分。
1. 将本地项目上传到服务器
我们打包上传,还是git克隆都行,总之将本地项目上传到了服务器。
[root@cs mtb]# pwd
/opt/mtb # 注意我将前后端项目都上传到了/opt/mtb目录下
[root@cs mtb]# ll
total 20
drwxr-xr-x 6 root root 4096 Jul 14 17:06 mtb_client # vue项目
drwxr-xr-x 8 root root 4096 Jun 2 22:13 mtb_server # django后端的项目
项目上传到服务器之后,我们就可以着手进行部署配置了。
我的后端项目目录中包含requirements.txt
和初始的mtb.sql
数据文件,方便后续导入后,能直接启动项目。
这里我们先来配置后端。
2. 后端部署流程
2.1 创建虚拟环境
这里要做事儿就不少,先要创建虚拟环境:
[root@cs mtb]# pwd
/data/mtb
[root@cs mtb]# pip3.9 install virtualenv==20.14.1 # 安装virtualenv,你装过了就不用再装了
[root@cs mtb]# virtualenv --python=python3.9 env # 创建虚拟环境
[root@cs mtb]# ll
total 20
drwxr-xr-x 7 root root 4096 Jul 14 17:36 mtb_client
drwxr-xr-x 8 root root 4096 Jun 2 22:13 mtb_server
drwxr-xr-x 4 root root 4096 Jun 2 21:03 venv # 创建虚拟环境叫做venv
接下来就要激活这个虚拟环境了:
[root@cs mtb]# pwd
/opt/mtb
[root@cs mtb]# source venv/bin/activate # 激活虚拟环境
(venv) [root@cs mtb]# pip install -r ./mtb_server/requirements.txt # 从django项目目录中安装项目依赖
2.2 将初始数据导入到MySQL
我项目中用到了MySQL数据库,并且,我也同步上传了初始的数据文件,所以接下来我们要把项目用的数据库搞出来,然后把数据录入。
首先项目关于MySQL的配置在这:
[root@cs mtb]# pwd
/opt/mtb
[root@cs mtb]# cat ./mtb_server/mtb/local_settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'mtb', # 你的数据库名称
'USER': 'root', # 你的数据库用户名
'PASSWORD': '123', # 你的数据库密码
'HOST': '127.0.0.1', # 你的数据库主机,留空默认为localhost
'PORT': '3306', # 你的数据库端口
}
}
REST_FRAMEWORK = {
"UNAUTHENTICATED_USER": lambda: None,
"UNAUTHENTICATED_TOKEN": lambda: None,
"DEFAULT_AUTHENTICATION_CLASSES": ["utils.ext.auth.JwtTokenAuthentication", ],
}
然后就可以执行导入命令,进行初始化数据了:
[root@cs mtb]# mysql -uroot -p123 <./mtb_server/mtb.sql
mysql: [Warning] Using a password on the command line interface can be insecure.
[root@cs mtb]# mysql -uroot -p123 -e "select * from mtb.base_userinfo;" # 数据也有了
mysql: [Warning] Using a password on the command line interface can be insecure.
+----+----------+----------+
| id | username | password |
+----+----------+----------+
| 1 | root | root1234 |
+----+----------+----------+
SQL文件中,会自动创建数据库,这里就不用手动创建了。
2.3 测试是否可以访问成功
现在我们基本可以跑一跑项目,测试下能否启动成功了。
(venv) [root@cs mtb]# pwd
/opt/mtb
(venv) [root@cs mtb]# python ./mtb_server/manage.py runserver 0.0.0.0:8888
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
July 14, 2022 - 18:04:56
Django version 3.2, using settings 'mtb.settings'
Starting development server at http://0.0.0.0:8888/
Quit the server with CONTROL-C.
然后浏览器就可以继续访问测试下http://www.neeo.cc:8888/api/base/test/?format=json
,返回"TEST OK"
的话,这就是配置的没有问题。
nice,现在项目能正常访问。
2.4 uwsgi配置
既然项目能正常访问,那我们继续往下进行uwsgi的配置:
(venv) [root@cs mtb]# pip install uwsgi # 先下载uwsgi
(venv) [root@cs mtb]# vim uwsgi.ini # 创建uwsgi.ini文件
(venv) [root@cs mtb]# cat uwsgi.ini # 写入内容如下
[uwsgi]
# 填写mtb项目的根目录
chdir=/opt/mtb/mtb_server/
# 填写与项目同名的目录,这是个相对路径,主要就是找到其内的wsgi.py这个文件
module=mtb.wsgi
# 虚拟环境的根目录,也就是工作目录
home=/opt/mtb/venv
# uwsgi的主进程,其他的uwsgi的进程都是这个主进程的子进程,当你kill时,杀掉的也是这个master主进程
master=true
# uwsgi并发时的工作进程的数量,官网的建议是:2 * cup核数 + 1
# 由这几个进程来分摊并发请求
processes=3
# 临时使用http,实际部署时,通过nginx反向代理
http=0.0.0.0:8888
# socket=0.0.0.0:8888
# 当服务器退出时,自动删除unix socket文件和pid文件
vacuum=true
# uwsgi内部解析的数据包大小,默认4k,我这里调大些,否则会报:invalid request block size: 21573 (max 4096)...skip
buffer-size=65536
配置好了,就可以启动下:
[uWSGI] getting INI configuration from uwsgi.ini
然后浏览器就可以继续访问测试下http://www.neeo.cc:8888/api/base/test/?format=json
,还是会返回"TEST OK"
,这就是配置的没有问题。
2.5 配置supervisor管理uwsgi
这个其实是可选的选项,不过我通常喜欢用supervisor来管理uwsgi,减少宕机几率。
来看怎么配置吧。
(venv) [root@cs mtb]# which uwsgi # 找一下uwsgi的绝对路径,注意这个路径一定是你当前虚拟环境的中bin中uwsgi,别找到其它虚拟环境中了
/opt/mtb/venv/bin/uwsgi
(venv) [root@cs mtb]# pwd
/opt/mtb
(venv) [root@cs mtb]# cat /etc/supervisord.conf # 其它的输出我都删了,只保留关于mtb项目的配置
[program:mtb]
command=/opt/mtb/venv/bin/uwsgi --ini /opt/mtb/uwsgi.ini ; 都使用绝对路径
autostart=true ; 在supervisord启动的时候也自动启动
startsecs=10 ; 启动10秒后没有异常退出,就表示进程正常启动了,默认为1秒
autorestart=true ; 程序退出后自动重启,可选值:[unexpected,true,false],默认为unexpected,表示进程意外杀死后才重启
stopasgroup=true ;默认为false,进程被杀死时,是否向这个进程组发送stop信号,包括子进程
killasgroup=true ;默认为false,向进程组发送kill信号,包括子进程
user=root
然后后使用supervisor进行管理它,下面列出相关的命令,supervisor的命令参考:https://www.cnblogs.com/Neeo/p/8651136.html
# 启动supervisor,默认会启动内部管理的进程
supervisord -c /etc/supervisord.conf #启动supervisor服务端,指定配置文件启动
# 检查supervisor是否存在了进程,是否启动
ps -ef|grep supervisord
ps aux | grep supervisord
# 杀掉supervisor进程
pkill -9 supervisord
# 重新加载配置信息
supervisorctl reload
# 根据最新的配置文件,启动新配置或有改动的进程,配置没有改动的进程不会受影响而重启
supervisorctl update
# 设置supervisor开机自启
systemctl enable supervisord
# 停止某一个进程,program 就是进程名称,在ini文件首行定义的[program:mofang_celery_flower] 里的 :的名称
supervisorctl stop program
supervisorctl start program # 启动某个进程
supervisorctl restart program # 重启某个进程
supervisorctl stop groupworker: # 结束所有属于名为 groupworker 这个分组的进程 (start,restart 同理)
supervisorctl stop groupworker:name1 # 结束 groupworker:name1 这个进程 (start,restart 同理)
supervisorctl stop all # 停止全部进程,注:start、restartUnlinking stale socket /tmp/supervisor.sock、stop 都不会载入最新的配置文件
# 进入supervisor任务管理终端
# 任务管理终端提供了这些命令
supervisorctl -c /etc/supervisord.conf
[root@cs crm]# supervisorctl -c /etc/supervisord.conf
mtb STOPPED May 02 02:42 PM
supervisor> start all
supervisor> start newcrm
supervisor> stop newcrm
supervisor> stop all
supervisor> status
supervisor> exit
[root@cs crm]#
让supervisor管理着uwsgi,在后台运行着就行了。
2.5 配置nginx反向代理
我们希望将来的客户端访问nginx的8700端口(我这里用8700,你可以是其它端口),然后又nginx再转发给uwsgi的8888端口,这样django后端不用直接跟前端打交道,前面套个nginx,比较安全。
来看怎么配置:
(venv) [root@cs mtb]# pwd
/opt/mtb
(venv) [root@cs mtb]# cat /opt/tngx233/conf/nginx.conf
user root;
worker_processes 1;
events {
worker_connections 1024;
}
pid logs/nginx.pid;
error_log logs/error.log;
http {
include mime.types;
default_type application/octet-stream;
# 就是这块,转发到mtb的uwsgi
server {
listen 8700;
server_name _;
# nginx的8700端口,然后直接转发给后端8888端口的uwsgi
location / {
uwsgi_pass 0.0.0.0:8888;
include uwsgi_params;
}
}
}
然后平滑重启nginx:
(venv) [root@cs mtb]# nginx -t
nginx: the configuration file /opt/tngx233//conf/nginx.conf syntax is ok
nginx: configuration file /opt/tngx233//conf/nginx.conf test is successful
(venv) [root@cs mtb]# nginx -s reload
(venv) [root@cs mtb]#
没完,别着急浏览器访问呢!咱们还有个事儿没干,那就是修改uwsgi的配置:
(venv) [root@cs mtb]# pwd
/opt/mtb
(venv) [root@cs mtb]# vim uwsgi.ini
(venv) [root@cs mtb]# cat uwsgi.ini
[uwsgi]
# 填写mtb项目的根目录
chdir=/opt/mtb/mtb_server/
# 填写与项目同名的目录,这是个相对路径,主要就是找到其内的wsgi.py这个文件
module=mtb.wsgi
# 虚拟环境的根目录,也就是工作目录
home=/opt/mtb/venv
# uwsgi的主进程,其他的uwsgi的进程都是这个主进程的子进程,当你kill时,杀掉的也是这个master主进程
master=true
# uwsgi并发时的工作进程的数量,官网的建议是:2 * cup核数 + 1
# 由这几个进程来分摊并发请求
processes=3
# 临时使用http,实际部署时,通过nginx反向代理
# ---------- 就这块,最开始测试的时,用的http=0.0.0.0:8888,现在用nginx反向代理了,我们要用socket=0.0.0.0:8888 ----------
#http=0.0.0.0:8888
socket=0.0.0.0:8888
# 当服务器退出时,自动删除unix socket文件和pid文件
vacuum=true
# uwsgi内部解析的数据包大小,默认4k,我这里调大些,否则会报:invalid request block size: 21573 (max 4096)...skip
buffer-size=65536
然后使用supervisor重启uwsgi。
(venv) [root@cs mtb]# supervisorctl restart mtb
mtb: stopped
mtb: started
(venv) [root@cs mtb]#
这个时候,再去浏览器,访问http://www.neeo.cc:8700/api/base/test/?format=json
,就能得到"TEST OK"
了。
这下,我们后端的部署,算是完成了。
3. 前端部署流程
后端部署好了,我们来看下前端怎么搞。
3.1 前端项目打包
我们要生成dist,由于我用的服务器是我的测试服务器,所以vue的整个项目都在上面,我呢就懒省事,直接在这个项目中npm run build
,生成的dist目录就直接配置了。你其实可以在本地打包好,直接将dist上传到服务器即可。
确认base url指向了后端nginx代理的8700端口
一定要确保你的前端的项目中,所有向后端发送请求,如axios请求,都要改为上面django后端配置nginx反向代理的8700端口。
比如测试环境配置的baseurl是127.0.0.1:8000
,那么在部署到服务器上,这里都要统一改为现在的8700端口。
// 原来我测试环境下的用的是8000端口
axios.defaults.baseURL = 'http://www.neeo.cc:8000/api'
axios.defaults.baseURL = 'http://www.neeo.cc:8000/api'
至于在哪里修改,就要看你的项目是怎么写的了。我这里只要改/opt/mtb/mtb_client/src/plugins/axios.js
中baseurl这一行就行了。
完事之后,就可以进行打包了。
打包项目
(venv) [root@cs mtb]# pwd # 注意我在哪个目录操作的,另外,这个时候,就不用管是否激活了python的虚拟环境了
/opt/mtb
(venv) [root@cs mtb]# ls mtb_client/
babel.config.js node_modules package.json package-lock.json public README.md src
(venv) [root@cs mtb]# cd mtb_client/
(venv) [root@cs mtb_client]# npm run build
(venv) [root@cs mtb_client]# ll
total 1148
-rw-r--r-- 1 root root 73 Jun 2 21:58 babel.config.js
drwxr-xr-x 5 root root 4096 Jul 14 17:36 dist # 打包生成的dist
drwxr-xr-x 841 root root 36864 Jun 2 22:05 node_modules
-rw-r--r-- 1 root root 1202 Jun 2 21:58 package.json
-rw-r--r-- 1 root root 1111391 Jun 2 22:05 package-lock.json
drwxr-xr-x 2 root root 4096 Jun 2 21:58 public
-rw-r--r-- 1 root root 548 Jun 2 21:58 README.md
drwxr-xr-x 8 root root 4096 Jun 2 21:58 src
3.2 配置nginx代理
前端部署比较简单,直接在nginx中配置个server就行了。
(venv) [root@cs mtb]# pwd
/opt/mtb
(venv) [root@cs mtb]# cat /opt/tngx233/conf/nginx.conf
user root;
worker_processes 1;
events {
worker_connections 1024;
}
pid logs/nginx.pid;
error_log logs/error.log;
http {
include mime.types;
default_type application/octet-stream;
# 就是这块,转发到mtb的uwsgi
server {
listen 8700;
server_name _;
# nginx的8700端口,然后直接转发给后端8888端口的uwsgi
location / {
uwsgi_pass 0.0.0.0:8888;
include uwsgi_params;
}
}
# mtb前端的nginx反向代理
server {
listen 80;
server_name _;
location / {
# try_files解决页面刷新,不会出现404的问题,如果你的vue页面刷新时返回404,就加上这个参数
try_files $uri $uri/ @rewrites;
# 直接返回vue打包生成的dist绝对路径即可
root /opt/mtb/mtb_client/dist;
index index.html;
}
location @rewrites {
rewrite ^.*$ /index.html last;
}
}
}
完事之后平滑重启,然后前端就可以直接通过http://www.neeo.cc/
访问,然后会自动跳到login页面,然后输入用户名(root)和密码(root1234)即可登录成功。
ssl证书认证
接下来,就要在上面的基础上,开始进行添加证书这块了。
我们先来搞个简单的,就是为前端配置上证书,这样,浏览器通过https和vue前端进行打交道,然后vue和django后端还是通过http的形式。
证书获取
证书的话,腾讯云和阿里云都有ssl证书,也有免费一年的。
我这里以阿里云为例。
1. 证书购买
我这里以免费的证书为例。
首先,访问阿里云主页,搜索ssl证书,然后点击"立即购买"。
然后,选一个能免费试用(一年)的,当然你也可以买个收费的。
2. 控制台中申请证书
在你的控制台,找到"SSL证书"选项,点击"免费证书",点击"创建证书",这样就能创建出来一个证书了。
创建出来一个证书后,就出现在了证书列表中了。
在证书列表中,点击"申请证书"。
然后一顿编辑,输入证书绑定的域名,然后联系人这些,完事点击下一步。
然后提交审核,完事等审核结果,然后大约几分钟就行了,你可以刷新页面进行尝试,直到等到"已签发"就行了。
3. 将证书上传到服务器
当审核通过,就可以点击"下载",选择"Nginx",就下载到了本地,然后将这两个扩展名为.key
和.pem
的文件,上传到服务器。
(venv) [root@cs mtb]# pwd
/opt/mtb
(venv) [root@cs mtb]# ll
total 32
-rw-r--r-- 1 root root 1675 Jul 15 22:00 8124087_www.neeo.cc.key # 就这两个
-rw-r--r-- 1 root root 3801 Jul 15 22:00 8124087_www.neeo.cc.pem # 就这两个
drwxr-xr-x 2 root root 4096 Jun 2 22:14 hook
drwxr-xr-x 7 root root 4096 Jul 15 18:25 mtb_client
drwxr-xr-x 8 root root 4096 Jul 14 18:09 mtb_server
-rw-r--r-- 1 root root 148 Jun 2 21:04 test.py
-rw-r--r-- 1 root root 887 Jul 14 21:35 uwsgi.ini
drwxr-xr-x 4 root root 4096 Jun 2 21:03 venv
配置客户端的ssl
python manage.py runsslserver --cert /opt/mtb/8124087_www.neeo.cc.pem --key /opt/mtb/8124087_www.neeo.cc.key 0.0.0.0:9200