CentOS 7 下Django项目部署教程(基于uwsgi和Nginx)
本文主要介绍如何在Linux平台上部署Django相关项目,关于Django项目的部署在互联网论坛上有很多的资料,笔者在查阅众多资料并经过实践后发现结果并不如意(或多或少总是遇到一些问题,往往与资料的预期不相符)。在浏览了许多资料后笔者整理得出了部署Django项目的一般性方法,部署的方法有很多种,在此笔者选择了较为常用的基于uwsgi和Nginx的部署方案。
一、前提准备
部署前主要是需要做一些与服务器相关的准备工作,本次教程的服务器采用了阿里云的 CentOS 7.3 64位,当然作为资料学习大家也可使用Linux虚拟机进行部署。另外,为了方便的Linux的使用和部署操作,在此推荐大家安装XSHELL(https://www.netsarang.com/en/xshell/)和XFTP(https://www.netsarang.com/en/xftp/),XSHELL主要是用于连接服务器并进行终端操作,而XFTP则可用来进行服务器与开发主机的文件传输(比如windows和linux间的传输)。
在此还需要注意的是,如果大家和我一样使用阿里云服务器,那么在部署前还需要留意一下设置相应的网络安全组,这个安全组主要是用于设置外网对服务器端口的访问权限,由于阿里云服务器中有的端口默认未开启被访问,所以为了能够让外网访问到部署的项目(比如Django网站),那么就需要开启相应的端口(比如80端口)。安全组设置可在阿里云控制台(https://ecs.console.aliyun.com/)的服务器实例中查看到,如下左边功能栏的【本实例安全组】,点击进入后可在安全组列表中查看到相关规则设置,点击【配置规则】后便可进行端口访问权限的设置(比如下图中新设置的80和8000端口)。
二、部署所需要安装软件的清单
本篇采用uwsgi和nginx的部署方案,因此在Linux环境下我们需要预先安装好以下软件,不过在此只做简单的描述,读者们有一个概念性的印象便可(如果想要深入理解可自行学习相关资料),各个软件具体的安装方法和使用操作将在后文一一讲述。
- Python:因Lunix系统默认安装了python2版本,但由于现在的Django项目主流是采用python3开发,因此我们还需要在服务器中安装好python3的版本,并配置相关的环境变量以便在终端的直接使用。对于Linux下python3环境的安装与搭建这一部分,限于篇幅,在此不进行阐述,各位读者可以到互联网上查询相关的资料。
- uwsgi:uwsgi是一个基于python的应用服务器,它可充当网络请求中文件的传输,也可以用于启动Django项目。在我们的Django项目部署中,一般让其充当非静态文件的资源访问中间服务器,外网可以借助于它来访问Django项目的非静态文件资源。当然,uwsgi也可以传输静态资源,但在这一点上其性能并不高。
- nginx:nginx是一个高性能的HTTP和反向代理web服务器,它主要负责转发外网的端口访问请求,比如它可转发80端口至uwsgi进程以访问相关网站,而二者之间的联系可通过socket进行关联。另外由于nginx转发性能之高,也可以用来做相关服务器,在Django项目中如果说uwsgi充当非静态资源的中间服务器,那么nginx充当的角色便是静态资源的中间服务器,它可以通过转发特定的静态http 请求来让外网访问到Django的静态文件资源。
- supervisor:supervisor是一个进程管理工具,可通过fork/exec的方式将这些被管理的进程当作supervisor的子进程来启动,并且当监听的子进程异常中断时,它还可以捕获到相关信息并进行异常处理(比如重新启动子进程)。在Django项目中,由于uwsgi命令行启动Django项目是依赖于uwsgi进程的,当进程结束后Django项目也随之结束,因此部署时我们可以把“启动Django项目”的进程(比如uwsgi进程)作为supervisor的一个子进程,并开启supervisor服务,以便在终端断开后对部署进行监听与管理。在supervisor中,包括supervisord和supervisorctl两部分,前者为核心功能模块,充当命令行命令功能,而后者则是一个控制台(类似于mysql控制台),亦可对进程进行管理。
总的来说,以上几个模块在Django项目中的关系可表述为下图:
以上为部署项目最基本的软件需求,具体的软件环境还需要结合实际情况进行配置(比如一些项目可能需要mysql、memcache和redis等环境,那么还需要进行相关环境的搭建)
三、正式部署
本次部署工作分为两个环节——开发主机和服务器主机,开发主机主要负责项目的开发与调试,确保项目质检合格后方可在服务器主机中进行部署与运维操作。
(一)开发主机
在此以全新的Django 3.0项目为例进行阐述,并预先创建好了一个测试用的testapp,其主要是用于展示一个测试网站首页,整体项目架构如下图所示:
1. 测试Django项目
开启DEBUG,在终端输入如下命令开启项目,并在浏览器访问127.0.0.1:8000,观察项目是否正常运行
$ python manage.py runserver 0.0.0.0:8000
2. 打包项目环境依赖
关闭DEBUG,并在settings,py中设置ALLOWED_HOSTS和STATIC_ROOT两个常量
- ALLOWED_HOSTS:用于设置可访问的域名地址,即待部署服务器的域名或公网IP。
- STATIC_ROOT:用于设置静态资源的收集目录,在服务器项目中通过运行命令可将项目所有的静态资源收集起来以方便后续Nginx的转发访问。
在此,笔者为方便DEBUG的切换,将两种模式下的设置进行了如下整合:
# SECURITY WARNING: don‘t run with debug turned on in production! DEBUG = True if DEBUG == True: # 开发模式下允许所有域名访问 ALLOWED_HOSTS = [‘*‘] else: # 发行模式下允许访问的域名地址 ALLOWED_HOSTS = [‘XXX.XXX.XXX.XXX‘] # …… # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/3.0/howto/static-files/ STATIC_URL = ‘/static/‘ STATICFILES_DIRS = ( os.path.join(BASE_DIR, ‘static‘), ) if DEBUG == False: # 发行模式下设置静态文件收集目录,收集静态文件以便后续 Nginx 的配置 STATIC_ROOT = os.path.join(BASE_DIR, ‘static_dist‘)
之后运行命令打包项目的虚拟环境依赖,命令完成后在项目根目录下可见到新生成的requirements.txt文件,这里面记录着本项目所依赖的pip包,以便后续在服务器中的安装。
$ pip freeze > requirements.txt
# requirements.txt
asgiref==3.2.3
Django==3.0.3
pytz==2019.3
sqlparse==0.3.0
3. 项目源文件迁移
将项目源文件(不含venv虚拟环境文件夹)通过XFTP传输到服务器中(比如本教程将其迁移至服务器下的’/srv/Django_projects/DjangoDistTest/’目录下)
至此,开发主机的工作已全部完成.
(二)服务器主机(注:该教程中所有Linux命令均在root权限下操作)
1. 安装python3环境和virtualenv虚拟环境管理工具
Linux下Python3环境的安装在此不进行阐述,这里主要讲解virtualenv的安装与使用,同时为方便后文的讲述,假设我们的python3安装目录为‘/usr/local/python3’。
virtualenv是python的一个虚拟环境管理工具,通过它可以很方便地创建一个python虚拟环境(这里稍微补充一下,虚拟环境是指拷贝式地创建一个与系统python版本一模一样的python运行环境,但这个环境不包含任何多余的依赖包,我们可以在这个虚拟环境中根据项目针对性地安装一些依赖包,从而方便python项目的管理并减少包的冗余)。
安装命令
$ pip3 install virtualenv
设置软链接
上文已经说明,软链接是为了将一程序配置为命令以方便Linux直接在终端通过命令行进行操作
$ ln -s /usr/local/python3/bin/virtualenv /usr/bin/virtualenv
使用方法
直接在我们的项目目录下执行相关命令,其中参数’python’指向所拷贝的源python程序
$ cd /srv/django_projects/DjangoDistTest $ virtualenv --python=/usr/local/python3/bin/python3 venv
2. 安装项目环境依赖并验证
开启虚拟环境,同时检查所安装的包
$ source ./venv/bin/activate $ (venv) pip list
安装项目依赖包,之后再次查看包若发现已装上全部依赖则表示虚拟环境已搭建好
$ pip3 install -r requirements.txt
执行’python manage.py makemigrations’和’python manage.py migrate’进行数据库迁移(如果之前将.sqlite3文件拷贝过来了,那么迁移时可能会不同,删除.sqlite3文件即可;另外,对于不同版本的Linux,这一步可能会出现sqlite3文件错误,原因是系统未安装sqlite3,因此查阅相关资料安装sqlite3即可)
$ (venv) python manage.py makemigrations $ (venv) python manage.py migrate
由于我们项目现在的DEBUG为关闭状态,考虑到上文中的STATIC_ROOT设置,所以需要收集静态文件资源(关于静态资源路由的设置请参看文末附录)
$ (venv) python manage.py collectstatic
之后运再次运行项目,在浏览器中访问网址即可(服务器公网IP:8000或域名:8000)。另外,这里还需要留意一下阿里云安全组是否已经设置好。
3. 安装uwsgi
安装命令
由于uwsgi是基于python编写的,因此我们可以直接通过pip进行安装(笔者之前在查阅资料时发现有的博主是通过CentOS 的yum进行安装的,不过经实践后操作效果不是那么好,因此还是推荐使用pip进行安装)。这里需要注意的是,uwsgi由于是通过系统进程来调用,所以要在系统级别中安装,因此我们需要预先退出虚拟环境再进行安装。
$ (venv) deactivate $ pip3 install uwsgi
建立软链接
$ ln -s /usr/local/python3/bin/uwsgi /usr/bin/uwsgi
验证安装
直接使用uwsgi命令行形式开启项目,参数http表示端口号,module表示项目的wsgi文件,home表示所使用的虚拟环境目录
$ uwsgi --http :8000 --module DjangoDistTest.wsgi --home=/srv/django_projects/DjangoDistTest/venv/
之后使用浏览器进行访问即可
上面这种通过命令行的方法已经可以启动项目,但如果每次启动项目都输入一长串命令的话会比较费力,因此下面介绍通过ini文件配置的方式启动项目
uwsgi.ini文件配置
在项目根目录下新建ini文件(比如本例中的DjangoDistTest_uwsgi.ini),并输入以下配置信息,之后便可通过运行命令’uwsgi –ini DjangoDistTest_uwsgi.ini’来启动该项目了
# DjangoDistTest_uwsgi.ini [uwsgi] # Django相关的设置 # 项目根目录 chdir = /srv/django_projects/DjangoDistTest # Django的wsgi文件 module = DjangoDistTest.wsgi # 虚拟环境路径 home = /srv/django_projects/DjangoDistTest/venv/ # 指定端口 http = :8000 # Django 和 uwsgi的相关日志记录位置,注意要预先在项目中新建log文件夹 daemonize = /srv/django_projects/DjangoDistTest/log/uwsgi.log # 进程相关的设置 # 主进程 master = true # 最大数量的工作进程 processes = 10 # socket文件路径,用于与 Nginx 进行通信 socket = /srv/django_projects/DjangoDistTest/DjangoDistTest.sock # 设置socket文件的权限 chmod-socket = 666 # 退出时是否清理环境 vacuum = true
$ uwsgi –ini DjangoDistTest_uwsgi.ini
4. 安装Nginx
安装命令
Nginx服务可以直接通过yum命令进行安装
$ yum install nginx’
验证安装
安装完成以后,使用命令’systemctl start nginx’即可开启nginx服务,之后使用浏览器访问服务器公网ip(即http 80端口),若出现如下界面则表示nginx已成功启动(有的系统可能会出现”Welcome to NGINX!”的欢迎界面,这两种都是可以的,主要与系统版本和配置有关)
$ systemctl start nginx
当然,也可以通过命令’systemctl status nginx’查看nginx服务的状态
$ systemctl status nginx
此外,还有相对应的restart和stop命令控制重启和停止,后续感兴趣的同学也可以把Nginx服务设置成开机自动启动。(这里再补充一下下,对于以前版本的CentOS,需要将命令改写成对应的”service nginx XXX”格式)
关联uwsgi和Nginx
在完成好uwsgi和Nginx的安装后,我们便可通过Nginx配置将二者进行关联,即当外网访问某一端口(比如80端口)时Nginx会自动转发至相应的uwsgi服务器进行处理。这一关联的映射文件存放在’/etc/nginx/conf.d’目录下(新安装的Nginx可能没有该文件夹,需要自己手动创建一下),因此,我们在该目录下新建相关映射文件DjangoDistTest.conf。(注意下面的server_name填上公网ip或域名)
# DjangoDistTest.conf upstream DjangoDistTest { # 设置 socket 通信文件位置 server unix:///srv/django_projects/DjangoDistTest/DjangoDistTest.sock; } server { # 监听的端口号 listen 80; # 域名 server_name XXX.XXX.XXX.XXX; #如果有域名的话,就写上域名,比如"unikfox.cn wwwunikfox.cn XXX.XXX.XXX.XXX" charset utf-8; # 最大的文件上传尺寸 client_max_body_size 75M; # 转发非静态文件请求到Django服务器 location / { uwsgi_pass DjangoDistTest; # uwsgi_params文件地址 include /etc/nginx/uwsgi_params; } # 转发静态文件 http 请求 location /static { alias /srv/django_projects/DjangoDistTest/static_dist; } }
之后重新启动uwsgi和Nginx服务即可,由于上述配置中监听了80端口,因此现在我们只需要通过在浏览器访问服务器公网ip或域名即可访问Django项目了(而不需要再填写8000端口)
5. 使用supervisor管理进程
上文已经提到,uwsgi是一个进程,它有可能因为某些神秘力量而被迫终止,一旦uwsgi进程退出了那么它所对应的Django项目也就停止了,因此为了避免uwsgi的结束风险,我们可以使用supervisor工具进行进程管理,以使当uwsgi异常退出时能自行恢复。
安装方法
使用pip3在系统级中进行安装
$ pip3 install supervisor
建立软链接(包括supervisord和supervisorctl两部分)
$ ln -s /usr/local/python3/bin/supervisord /usr/bin/supervisord $ ln -s /usr/local/python3/bin/supervisorctl /usr/bin/supervisorctl
配置文件
接下来,在项目根目录下进行相关的文件配置即可(如本例中的”DjangoDistTest_supervisor.conf”)
# DjangoDistTest_supervisor.conf # supervisor程序名字 [program:DjangoDistTest] # supervisor执行命令 command = uwsgi --ini DjangoDistTest_uwsgi.ini # 项目的目录 directory = /srv/django_projects/DjangoDistTest # 开始的时候等待多少秒 startsecs = 0 # 停止的时候等待多时秒 stopwaitsecs = 0 # 自动开始 autostart = true # 程序挂了后自动重启 autorestart = true # 输出的log文件 stdout_logfile = /srv/django_projects/DjangoDistTest/log/supervisord.log # 输出的错误文件 stderr_logfile = /srv/django_projects/DjangoDistTest/log/supervisord.err [supervisord] # log的级别 loglevel = info # 设置supervisorctl管理员配置 [supervisorctl] # supervisorctl登录的的地址和端口号,端口号可自定义 serverurl = http://127.0.0.1:XXXX # supervisorctl的用户名和密码 username = unikfox password = 123456 [inet_http_server] # supervisor的服务器,与上面serverurl的端口号一致 port = :XXXX # 用户名和密码 username = unikfox password = 123456 [rpcinterface:supervisor] supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
启动命令
之后便可在项目根目录下使用命令启动supervisor进程
$ supervisord -c DjangoDistTest_supervisor.conf
对于进入管理控制台,可使用如下的命令
$ supervisorctl -c DjangoDistTest_supervisor.conf
常用的管理命令:
- status # 查看状态啊
- start program_name # 启动程序
- restart program_name # 重新启动程序
- stop program_name # 关闭程序
- reload # 重新加载DjangoTest_supervisor配置文件
- quit #推出控制台
使用‘help‘可查看supervisorctl所支持的所有命令
当然,除此以外,也还可以通过浏览器访问配置文件中serverurl的方式管理进程
如此一来,Django项目的部署便大功告成啦~完结撒花"o((>ω< ))o"
这里还需要注意一点的是,重启centOS后如需部署则需手动开启以下两个服务:
- 开启nginx服务:‘systemctl start nginx‘
- 开启相关项目的supervisor:‘supervisord -c DjangoDistTest_supervisor.conf‘
当然,大家也可以尝试把这两个设置成开机自动启动,这样就再也不用每次开机都手动输入命令啦。
附录——Django项目中urls.py下静态文件和图标的路由设置
# DjangoDistTest/urls.py from django.contrib import admin from django.urls import path,include # 处理网站图标 from django.views.generic.base import RedirectView # 处理静态文件的访问 from django.views import static from django.conf import settings from django.conf.urls import url urlpatterns = [ path(‘admin/‘, admin.site.urls), path(‘‘, include(‘testapp.urls‘)), url(r‘^favicon.ico$‘, RedirectView.as_view(url=r‘static/images/icon.ico‘)), #网站图标 ] + [ url(r‘^static/(?P<path>.*)$‘, static.serve, {‘document_root‘: settings.STATIC_ROOT}, name=‘static‘) #静态资源,只适用于DEBUG为False的情况 ]
以上便是本次的《CentOS 7 下Django项目部署教程(基于uwsgi和Nginx)》,Django项目的部署方式不止本案例一种,有关更多的部署方式大家可以查阅相关网络资料,重要的是,只要适合自己的方式那它就是好的方式。
关于本教程,如各位读者有一些疑问、想法或是更好的见解,欢迎留言交流与分享。