85407718 2020-02-09
本文主要介绍如何在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环境下我们需要预先安装好以下软件,不过在此只做简单的描述,读者们有一个概念性的印象便可(如果想要深入理解可自行学习相关资料),各个软件具体的安装方法和使用操作将在后文一一讲述。
总的来说,以上几个模块在Django项目中的关系可表述为下图:
以上为部署项目最基本的软件需求,具体的软件环境还需要结合实际情况进行配置(比如一些项目可能需要mysql、memcache和redis等环境,那么还需要进行相关环境的搭建)
本次部署工作分为两个环节——开发主机和服务器主机,开发主机主要负责项目的开发与调试,确保项目质检合格后方可在服务器主机中进行部署与运维操作。
在此以全新的Django 3.0项目为例进行阐述,并预先创建好了一个测试用的testapp,其主要是用于展示一个测试网站首页,整体项目架构如下图所示:
开启DEBUG,在终端输入如下命令开启项目,并在浏览器访问127.0.0.1:8000,观察项目是否正常运行
$ python manage.py runserver 0.0.0.0:8000
关闭DEBUG,并在settings,py中设置ALLOWED_HOSTS和STATIC_ROOT两个常量
在此,笔者为方便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
将项目源文件(不含venv虚拟环境文件夹)通过XFTP传输到服务器中(比如本教程将其迁移至服务器下的’/srv/Django_projects/DjangoDistTest/’目录下)
至此,开发主机的工作已全部完成.
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
开启虚拟环境,同时检查所安装的包
$ 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)。另外,这里还需要留意一下阿里云安全组是否已经设置好。
由于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文件配置的方式启动项目
在项目根目录下新建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
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的安装后,我们便可通过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端口)
上文已经提到,uwsgi是一个进程,它有可能因为某些神秘力量而被迫终止,一旦uwsgi进程退出了那么它所对应的Django项目也就停止了,因此为了避免uwsgi的结束风险,我们可以使用supervisor工具进行进程管理,以使当uwsgi异常退出时能自行恢复。
使用pip3在系统级中进行安装
$ pip3 install supervisor
$ 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
常用的管理命令:
使用‘help‘可查看supervisorctl所支持的所有命令
当然,除此以外,也还可以通过浏览器访问配置文件中serverurl的方式管理进程
如此一来,Django项目的部署便大功告成啦~完结撒花"o((>ω< ))o"
这里还需要注意一点的是,重启centOS后如需部署则需手动开启以下两个服务:
当然,大家也可以尝试把这两个设置成开机自动启动,这样就再也不用每次开机都手动输入命令啦。
# 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项目的部署方式不止本案例一种,有关更多的部署方式大家可以查阅相关网络资料,重要的是,只要适合自己的方式那它就是好的方式。
关于本教程,如各位读者有一些疑问、想法或是更好的见解,欢迎留言交流与分享。