CentOS 7 部署 Django :Python3 + virtualenv + Django + uWSGI + Nginx
相关介绍
以下内容绝大部分都需要 CentOS 7 联网,如果不能联网,请考虑其他相关分享。
环境&组件说明
- 操作系统:CentOS Linux release 7.6.1810 (Core)(升级之后变为CentOS Linux release 7.8.2003 (Core))
- Python版本:3.8.5
- pip版本:20.1.1(默认,一直提示,后升级到20.2.2)
- virtualenv版本:20.0.30
- django版本:3.0.8(应与开发版本对应)
- uwsgi版本:2.0.19.1
- nginx版本:1.18.0(stable version)
组件用途说明
- pip :是 Python 包管理工具,该工具提供了对Python 包的查找、下载、安装、卸载的功能。
- virtualenv:就是用来为一个应用创建一套“隔离”的Python运行环境。
- uWSGI:是一个Web服务器,它实现了WSGI协议、uwsgi、http等协议。
- Nginx (engine x): 是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务。
PS:以上只是简单概括介绍,还是建议去官网、论坛找些专门介绍的文章好好看一下。这样部署过程中遇到的问题,比较容易解决。
三种不同的部署方式
- python3 manage.py runserver部署 : 单线程,适合研发环境;
- uwsgi部署 : 多线程,增加了并发量;
- Nginx + uwsgi + django部署 : 前后端分离 + 多线程提高并发量, 适合生产环境中使用;
数据流如下:
准备阶段
下载Python安装包
CentOS更新/依赖下载
依次执行以下命令,确保相关依赖都已经安装或者更新:
# 升级内核(可以不升级)
yum update -y
# 安装开发工具(可以不安装)
yum -y groupinstall "Development tools"
# 安装相关依赖
yum -y install gcc openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel sqlite-devel libffi-devel tk-devel wget curl-devel
安装部署
最终的部署目标是达到可以在生产环境中使用,一共分为三个步骤,每个步骤的结果,都是可以使用的。
步骤一:Python命令启动
安装 Python
上传并解压文件,将文件 Python-3.8.5.tar.xz 解压为 Python-3.8.5.tar :
xz -d Python-3.8.5.tar.xz
将文件 Python-3.8.5.tar 解压为文件夹 Python-3.8.5 :
tar -xf Python-3.8.5.tar
也可以一步解压(但是按照 tar 的参数说明,以及 .tar.xz 的后缀名 应该是不能解压的。不理解!!! 抽空仔细研究研究)
tar xvf Python-3.8.5.tar.xz
进入文件夹
cd Python-3.8.5
配置安装路径:
./configure --prefix=/usr/local/python3
编译、安装:
make && make altinstall
安装完成之后 建立软链接 添加变量 方便在终端中直接使用python3
ln -s /usr/local/python3/bin/python3.8 /usr/bin/python3
Python3安装完成之后pip3也一块安装完成,不需要再单独安装.一样建立软链接:
ln -s /usr/local/python3/bin/pip3.8 /usr/bin/pip3
测试是否安装成功
python3 -V
pip3 -V
安装虚拟环境
pip3 install -i https://pypi.douban.com/simple/ virtualenv==20.0.30
建立软连接:
ln -s /usr/local/python3/bin/virtualenv /usr/bin/virtualenv
测试是否安装成功
virtualenv --version
安装成功在根目录下建立两个文件夹,主要用于存放env和网站文件的。(个人习惯,其它人可根据自己的实际情况处理)
mkdir -p /data/env
mkdir -p /data/wwwroot
切换到/data/env/下,创建指定版本的虚拟环境:
cd /data/env/
virtualenv --python=/usr/bin/python3 pyweb
进入虚拟环境目录:
cd /data/env/pyweb/bin
启动虚拟环境:
source activate
退出虚拟环境
# cd /data/env/pyweb/bin
deactivate
命令行最前边 “[” 之前出现(pyweb),则表示进入了虚拟环境。
在虚拟环境下,安装django:(这里指定了版本号,需要和开发环境一致)
pip3 install -i https://pypi.douban.com/simple django==3.0.8
测试是否安装成功及查看版本:
python3 -m django --version
部署
上传本地开发的 django 代码到目录 /data/wwwroot/ 中,进入项目目录,启动服务。(示例中直接用的都是 Django Admin 管理工具的页面。 Django 3.0.8 默认就是激活的)启动服务的方式有两种。
首先,进入项目目录,然后启动服务。
1、不允许外网访问的启动方式:
python3 manage.py runserver
测试是否启动成功:
curl http://127.0.0.1:8000/
2、允许外网访问,需要修改代码:
settings.py 中修改
ALLOWED_HOSTS = ['*']
启动命令:
python3 manage.py runserver 0.0.0.0:8000
本地测试,是否启动成功
curl http://0.0.0.0:8000/
测试是否可以外网访问。PC 打开浏览器,输入地址
http://ip:port
或者
http://ip:port/admin
如果本地测试成功,外网访问失败。需要查看防火墙是否启用,端口是否开放。默认的 CentOS 7 的防火墙是启动,并且端口是不开放的。
systemctl status firewalld # 查看防火墙是否启用
firewall-cmd --zone=public --list-ports # 查看哪些端口开放
PS : 这里部署的时候,会出现很多情况。例如:缺少 pymysql 依赖, sqllite 版本不匹配等。因此,很多人写博客的时候,都是直接在 CentOS 上面建立 django 项目。作为测试、学习,可以直接在 CentOS 上面直接建立 django 项目。但是,个人感觉既然目标是生产环境的部署,那还是要掌握如何处理异常的。毕竟这个坑,早晚是要填的~~
缺少 pymysql 依赖(提示 : ModuleNotFoundError: No module named ‘pymysql’ ), 利用 pip 安装即可(注意版本)。
pip3 install -i https://pypi.douban.com/simple pymysql
sqlite 版本不匹配,需要下载安装包,然后再安装。
步骤二:uwsgi部署
虚拟环境下,安装uwsgi:
pip3 install -i https://pypi.douban.com/simple uwsgi==2.0.19.1
给uwsgi建立软链接,方便使用
ln -s /usr/local/python3/bin/uwsgi /usr/bin/uwsgi
测试是否安装成功,及查看版本:
uwsgi --version
uwsgi 配置文件 myconf.yaml , 如下:(项目目录 chdir 、 pid 文件中的目录、module 文件名, 需要根据项目名称更改。这里的项目名称是 HelloWorld)
uwsgi:
# socket 不能通过浏览器访问,访问报错。提示 : invalid request block size: 21573 (max 4096)...skip 。 但是使用 Nginx 的时候,需要使用这个配置。
# socket: 127.0.0.1:8000
# 可以本地访问,不能外网访问
# http: 127.0.0.1:8000
# 外网访问 需要设置为 0.0.0.0:8000
http-socket: 0.0.0.0:8000
# 项目目录
chdir: /data/wwwroot/HelloWorld/
# 加载一个WSGI模块
module: HelloWorld.wsgi
# 启动工作进程数
processes: 4
# 日志文件
daemonize: uwsgi.log
# 启用master进程.启动主进程,来管理其他进程,其它的uwsgi进程都是这个master进程的子进程,如果kill这个master进程,相当于重启所有的uwsgi进程。
master: true
# 在每个worker而不是master中加载应用
lazy-apps: true
# 创建pid文件
pidfile: /data/wwwroot/HelloWorld/uwsgi.pid
部署启动 uwsgi 的命令
uwsgi --yaml myconf.yaml
测试是否启动成功。需要打开浏览器,输入地址
http://ip:port
或者
http://ip:port/admin
测试成功。停止 uwsgi ,后面需要修改配置,再启动:(这里的 pid 需要根据配置文件中的配置输入)
uwsgi --stop uwsgi.pid
uwsgi 使用帮助:
简单参数说明
官方.详细参数说明
官方.配置文件支持的格式及加载方式
步骤三:Nginx + uwsgi + django部署
Nginx安装
请参考官网, yum 安装, 非常简单。
PS : 安装的时候注意一下,使用 stable ,不建议使用 mainline 。
收集静态文件
需要修改代码, settings.py 中修改
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
收集静态文件的命令
python manage.py collectstatic
将静态文件上传到目录 /data/wwwroot/HelloWorld/static/ 中
修改 uwsgi 配置
uwsgi:
# socket 不能通过浏览器访问,访问报错 curl: (52) Empty reply from server 。日志中提示 : invalid request block size: 21573 (max 4096)...skip 。 但是使用 Nginx 的时候,需要使用这个配置。
socket: 127.0.0.1:8000 # 这里修改 - 这里修改 - 这里修改 - 这里修改 - 这里修改
# 可以本地访问,不能外网访问
# http: 127.0.0.1:8000
# 外网访问 需要设置为 0.0.0.0:8000
# http-socket: 0.0.0.0:8000 # 这里修改 - 这里修改 - 这里修改 - 这里修改 - 这里修改
# 项目目录
chdir: /data/wwwroot/HelloWorld/
# 加载一个WSGI模块
module: HelloWorld.wsgi
# 启动工作进程数
processes: 4
# 日志文件
daemonize: uwsgi.log
# 启用master进程.启动主进程,来管理其他进程,其它的uwsgi进程都是这个master进程的子进程,如果kill这个master进程,相当于重启所有的uwsgi进程。
master: true
# 在每个worker而不是master中加载应用
lazy-apps: true
# 创建pid文件
pidfile: /data/wwwroot/HelloWorld/uwsgi.pid
启动 uwsgi
uwsgi --yaml myconf.yaml
外网无法访问,不用开浏览器测试啦。
curl localhost:8000
运行以上命令,命令行报错 curl: (52) Empty reply from server, 日志文件中提示 invalid request block size: 21573 (max 4096)…skip 。不用处理,继续。
配置 Nginx
其实还需要配置 Nginx 目录下的 nginx.conf 文件,因为会涉及到 Nginx 的权限,默认 nginx 用户启动 Nginx 服务,但是一般和静态文件所在目录的权限都不是 nginx 用户。那这样就会导致访问的时候提示没有权限。
这里举例修改成 root 用户,具体哪个用户权限,需要根据部署的用户是哪个(相关参数参考官方网站)
#user nginx; 修改 nginx.conf 文件
user root; # 修改 nginx.conf 文件
目录 /etc/nginx/conf.d ,增加配置文件
server {
listen 8080;
# IPV6
listen [::]:8080;
server_name localhost;
proxy_set_header Host $host;
# client ip
proxy_set_header X-Real-IP $remote_addr;
# proxy ip
proxy_set_header X-Forwarded-For $remote_addr;
# proxy
location / {
include uwsgi_params;
uwsgi_pass 127.0.0.1:8000;
uwsgi_param UWSGI_SCRIPT HelloWorld.wsgi;
uwsgi_param UWSGI_CHDIR /data/wwwroot/HelloWorld;
}
location /static/ {
alias /data/wwwroot/HelloWorld/static/;
}
}
Nginx 重新加载配置文件
nginx -s reload
或者启动 Nginx
nginx
测试是否成功启动,浏览器打开(例子中使用的是 8080 端口)
http://ip:port
停止命令
nginx -s stop
尾声
原计划,以后的项目准备使用Django的,整个开发、测试流程下来感觉还挺好的。但是到了部署阶段,发现很多东西如果离线安装会比较麻烦,但是公司项目中大多数都是离线环境,为了不给实施人员挖坑。最终还是放弃了Django。虽然有点可惜,但是Django还是个非常不错的架构!