How to deploy django with wsgi
本文介绍如何部署nginx+uWSGI+Django的生产环境。
通过uWSGI和nginx部署你的Django项目
This tutorial is aimed at the Django user who wants to set up a production web server. It takes you through the steps required to set up Django so that it works nicely with uWSGI and nginx. 原文链接。
本教程的目标人群是那些希望部署自己的web server的Django用户。本教程会指引你按照步骤使Django与uWSGI和nginx很好的工作在一起。本教程对三个软件都有讲解,并提供了一整套工作流程。
Django使一种Python的high-level web框架,提倡快速开发与简洁的设计。
nginx使一款免费、开源、高性能的HTTP服务器,同时也可以作为反向代理或IMAP/POP3服务器
关于本教程
这只是一篇教程,并非是为了作为引用说明来编写的。请不要过分追求部署过程中过于详尽的细节。
对于Django部署来说,nginx和uWSGI都是很好的选择,但这并不是必须的,或者说官方的。这两款软件都非常棒,花费时间去研究他们是很值得的。
这里我们提供的Django部署方式是一个很好的方法,但并不是唯一的选择。在某些特定情况,这也许并不是最好的选择。
然而我们提供的方法将会是最可靠、最简单的方法。本教程所涵盖的内容将想你介绍一些你在使用任何软件部署Django时都需要了解的方法和策略。当像你展现了设置过程,并描述了进行这些设置的前提之后,你将掌握采用其他方法部署Django所需要的基本知识。
这篇文章针对你正在使用的系统做了部分假设。
我们假设你使用的是Unix-like系统,并且包含包管理系统。但是如果你想问像“Mac OSX中有什么包管理系统的替代品?”这样的问题,你可能很容易找到相关的答案。
并且,本教程针对1.4或更新版本的Django,这些版本的Django会在工程目录下自动创建wsgi模块。The instructions会针对之前的版本作介绍,你可能需要自己生成wsgi模块,并且Django工程的目录也会有些许不同。
为什么要这样做
Web服务器要面对外网的流量,它可以通过文件系统提供HTML、images、CSS等文件。但是Web服务器不能和Django应用直接通信,它需要某些程序运行这些Django应用,为其提供客户端传来的请求,并返回Django应用的回应。
Web Server Gateway Interface,也就是WSGI就是为了这个而存在的。WSGI is a Python standard。
uWSGI是WSGI的一种实现。在本教程中我们将通过设置uWSGI来创建一个Unix socket,以WSGI协议来向web服务器返回回应。最后我们将按照如下结构完成我们的部署。
the web client <-> the web server <-> the socket <-> uwsgi <-> Django
开始前要做的事
virtualenv
确保你在virtualenv中按照我们所需的软件(我们之后将介绍如何在系统范围内安装uwsgi)。
|
|
Django
在virtualenv环境中安装Django,创建新工程,并切换到工程目录中。
|
|
关于域名和端口
在本教程中我们可以将域名设置为example.com
。请按照你的实际环境配置。
在本教程全文中我们都将使用8000来作为我们发布的web server的端口,就像Django默认做的那样。你当然可以按照自己的意愿进行指定,但是我选这个端口的原因是一般的web server并不会选择8000这个端口,这样可以避免很多冲突。
uWSGI的基本安装与配置
在virtualenv环境中安装uWSGI
|
|
当然还有其他方式可以安装uWSGI,但是这种方法可以达到最好效果。记住你需要安装必须的Python开发组件。我们使用的环境是Debian,或基于Debian的Ubuntu,那么你需要安装pythonX.Y-dev
,这里的X.Y是你所使用的的Python的版本。
基础测试
创建一个名为test.py
的文件:
|
|
需要注意的是Python3需要传入bytes()
对象。
运行uWSGI:
|
|
各个选项的含义:
http :8000
:使用http协议,开放8000端口wsgi-file test.py
:加载指定的文件
上面一系列操作后,在浏览器访问8000端口,将得到hello world
的回应:
|
|
这说明如下的连接是联通的:
|
|
测试你的Django工程
现在我们希望使用uWSGI再做一次上面的事情,但这次我们要使用Django站点来替换test.py
的角色。
如果你还没有这么做过,那么首先要确保你的mysite
工程能够正常工作:
|
|
之后我们通过如下命令运行uWSGI
|
|
module mysite.wsgi
:加载所指定的wsgi模块。
通过浏览器访问服务器,如果站点正常出现,则证明uWSGI与Django合作的设置已经成功了,连接过程如下:
|
|
但正常情况下,我们不会让浏览器直接和uWSGI通信。和浏览器通信这个工作应该由web server来完成,就像中间人一样。
nginx基础
安装nginx
|
|
现在可以检查nginx是否已经成功在80端口提供了服务。当你看到了从nginx返回的“Welcome to nginx!”之后,则代表配置完成了。
|
|
如果80端口已经被其他服务占用,那你就需要重新配置nginx令其使用其他端口了。在本教程中,我们使用8000端口。
为你的站点配置nginx
为了完成配置工作,你需要获取nginx目录下的uwsgi_params
文件。你可以在nginx的conf目录中找到它,当然你可以在github上下载该文件:https://github.com/nginx/nginx/blob/master/conf/uwsgi_params
将该文件复制到你的Django工程根目录下,等一会我们会在nginx配置文件中引用它的所在路径。
现在创建一个名为mysite_nginx.conf
的文件,内容如下:
|
|
这个配置文件将告知nginx在处理Django有关的请求时,到指定目录中查找media和static文件。对于较大规模的工程,我们建议使用一个单独的server去处理static和media文件,由另一个来处理Django应用,但现在这些都不是问题。
在/etc/nginx/sites-enabled中创建软链接。
|
|
部署static文件
在运行nginx之前,你必须将Django的static文件都收集到static文件夹中。首先编辑mysite/settings.py
,添加内容:
|
|
然后运行
|
|
nginx基础测试
重启nginx
|
|
现在验证服务器是否正常工作,并且在/path/to/your/project/project/media directory
目录下添加一个文件media.png
,然后通过http://example.com:8000/media/media.png
查看是否能正常访问该文件。
如果不是直接重启nginx,而是先停止然后重新启动nginx的话,你可能会在发生错误时得到提示。
nginx、uWSGI和test.py
我们让nginx和返回“Hello World”的test.py程序联动起来。
|
|
这和之前的命令相同,只是这次我们换了一个新的端口。
nginx刚才已经通过配置使其通过8001端口来和uWSGI通信了,并且向外部开放8000端口以提供服务。此时可以访问http://example.com:8000。 工作流程如下:
|
|
此外,你还可以通过http://example.com:8001来访问uwsgi提供的服务,但此时你并不会得到所期望的内容,因为浏览器以http协议通信,而不是WSGI,但是你可以在运行uWSGI的终端看到部分输出。
使用Unix sockets代替端口
目前为止,我们一直使用TCP socket,因为它非常简单,但事实上使用Unix sockets是个更好的选择,因为它的额外开销更小。
编辑mysite_nginx.conf
,按照如下内容进行修改:
|
|
重启nginx,并重新运行uWSGI:
|
|
这一次socket选项说明了uWSGI通过哪个文件来使用Unix sockets。现在请再次访问http://example.com:8000以查看结果。
如果出现了问题
检查nginx的错误日志/var/log/nginx/error.log
。如果你看到了如下内容:
|
|
那就意味着你需要在使用uWSGI时指定权限以便nginx能够访问.sock文件。
|
|
你也可以将你的用户加入到nginx的用户组中(可能时www-data),或者vice-versa,以使nginx能够访问你创建的.sock文件。
让nginx在运行的终端持续输出日志是一个比较好的选择,因为这样你可以在出错时很快速的定位到问题所在。
在uwsgi和nginx的协助下运行Django应用
让我们通过下面的命令运行Django应用。
|
|
现在uWSGI和nginx应该已经可以提供Django应用的内容了。
在.ini文件中配置uWSGI
我们可以把uWSGI所使用的参数放到一个配置文件中,然后在uWSGI启动时指定该文件,这样可以简化很多操作。
创建名为mysite_uwsgi.ini
的文件:
|
|
然后如下运行uwsgi
|
|
我们Django站点又一次如期望的那样运行了。
在系统环境中安装uWSGI
目前为止,我们的uWSGI只安装在了virtualenv环境中,我们需要在系统环境中安装uWSGI来达到实际部署的目的。
退出你的virtualenv环境:
|
|
然后在系统环境中安装uWSGI
|
|
uWSGI wiki站点描述了多种安装步骤。在安装前请选择好版本,并以对应的方式进行安装。
检查你的uWSGI是否能正常工作:
|
|
Emperor模式
uWSGI可以运行在Emperor Mode中,在这种模式下,它将见识uWSGI配置文件所在目录,然后为每个以发现的配置文件生成一个实例(vassals/奴隶)。
无论何时修改配置文件,emperor都会自动的重新启动vassal。
|
|
你可能会需要以root权限运行uWSGI,各个选项含义:
emperor
:查找配置文件的目录uid
:当进程被启动时他的用户权限gid
:当进程被启动时它的用户组权限
检查站点是否仍然正常运行。
设置uWSGI开机启动
最后一步,我们要让uWSGI开机时自启动。
对于很多系统,最简单的设置方式是使用rc.local
。
编辑rc.local
并在exit 0
之前添加如下内容:
|
|
更多设置
一定要记得,这只是一篇让你入门的教程。如果想在生产环境中使用nginx和uWSGI,你需要阅读相关的详细文档。
nginx和uWSGI都有很有爱的社区,你可以在这些社区中找到关于配置和使用的建议。
nginx
如果你希望是nginx在生产环境中使用80端口,而不是8000端口,那么你在这篇教程中将不会找到答案。
你应该同时配置为非Django文件配置单独的服务。例如通过uWSGI访问static文件是件效率很低的事情。相反,你应该让nginx绕过uWSGI直接访问它们。
uWSGI
uWSGI支持多种配置的方式。具体可以查看uWSGI’s documentation 和 examples。
这篇教程中只提到了一部分uWSGI的选项,其他你应该了解的在生产环境中部署Django的参数如下:
|
|