Skip to content

环境准备

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证书"选项,点击"免费证书",点击"创建证书",这样就能创建出来一个证书了。

创建出来一个证书后,就出现在了证书列表中了。

1832671008083935232.png

在证书列表中,点击"申请证书"。

然后一顿编辑,输入证书绑定的域名,然后联系人这些,完事点击下一步。

1832671008650166272.png

然后提交审核,完事等审核结果,然后大约几分钟就行了,你可以刷新页面进行尝试,直到等到"已签发"就行了。

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