利用uWSGI和Nginx部署Django

主要内容来自于

https://uwsgi.readthedocs.io/en/latest/tutorials/Django_and_nginx.html

 

系统情况:

Ubuntu 14.04.2 LTS (实际是麒麟版)

python3 version 3.5.2(源上直接apt-get)

pip3 version 8.1.1(源上直接apt-get)

若无特殊指代,localhost即为127.0.0.1

 

虽说本文类别定为“翻译”,但是并没有将上述链接所代表的网页直接翻译,而是取得其中的关键步骤,另加自己的细节调整。

 

安装virtualenv并激活

安装virtualenv

我对virtualenv的理解非常浅,目前就理解为一种处理python多版本问题的“沙盒”解决方案,把想使用的python版本和对应的工具放到一个位置,不必担心系统层面的冲突。

 

实际安装时,使用

 

sudo pip3 install virtualenv

 

 

激活virtualenv

我目前理解激活(activate)virtualenv指创建一个virutalenv环境。由于我将使用python3,而在Ubuntu14中,系统的默认的python是2.7,那么在激活前的创建过程中需要指定所使用的python。在创建的同时需要指定一个virtualenv名称,virtualenv会创建相应的文件夹。实际创建virtualenv时使用如下命令

 

virtualenv -p /usr/bin/python3 uwsgi-tutorial

 

uwsgi-tutorial即指的是virtualenv名称,是沿用原网页上的描述。上述命令是我搜索得到的,原网页位置为stackoverflow。命令执行之后,会在当前文件夹下生成uwsgi-tutorial文件夹,进入该文件夹,那么我们现在所在位置为

 

/home/yaoyu/MySites/uwsgi-tutorial

 

其中yaoyu是我的用户名,MySites是我用来存放网站文件的位置(我就都不遮盖了。。)

 

此时,运行脚本bin/activate(该脚本位于/home/yaoyu/MySites/uwsgi-tutorial/bin)以激活该virtualenv

 

source bin/activate

pip install ipython

hash -r

 

成功激活后,终端的prompt会在最前面加上当前virtualenv的描述。上述第三条命令是令virtualenv重建对ipython的索引。参考这里。

 

在virtualenv中安装Django

安装Django,并创建一个示例project。

 

pip install Django

django-admin.py startproject mysite

cd mysite

 

mysite即为Django的project名,并且也是文件夹名(当然mysite下面还有一个mysite)。此时,我们的位置变为

 

/home/yaoyu/MySites/uwsgi-tutorial/mysite

 

可以现在立即测试Django project的可用性,并同时测一下端口的可用性。

 

python manage.py runserver 0:8000

 

若正常启动,则通过浏览器访问localhost:8000应能看到Django的信息。此时使用的是Django自带的development server,终端中用Ctrl+C终止Django的development server的运行。

 

在virtualenv中安装uWSGI

安装uWSGI(在CenOS中可能需要先安装python3x-devel,3x代表版本号)

 

pip install uWSGI

 

为了简单测试uWSGI,编写test.py文件。当前我们仍位于

 

/home/yaoyu/MySites/uwsgi-tutorial/mysite

 

新建的test.py文件内容为

 

def application(env, start_response):
	start_response('200 OK', [('Content-Type','text/html')])
	return [b"Hello World"] # python3

测试uWSGI的有效性

 

uwsgi --http :8000 --wsgi-file test.py

 

此时若正常启动uwsgi,那么通过浏览器访问localhost:8000即可看到Hello Word字样。Ctrl+C 终止uwsgi。

之后可测试uWSGI与刚刚建立的Django project的数据交换。

 

uwsgi --http :8000 --module mysite.wsgi

 

我们当前仍在/home/yaoyu/MySites/uwsgi-tutorial/mysite,module wsgi即保存在

 

/home/yaoyu/MySites/uwsgi-tutorial/mysite/mysite/wsgi.py

 

此时利用浏览器访问localhost:8000应当可以看到Django的信息。


安装并配置nginx

从源上直接安装nginx。

 

sudo apt-get install nginx

 

安装完毕后,启动nginx。

 

sudo /etc/init.d/nginx start

 

此时,使用浏览器访问localhost:80(注意端口,也可以不带端口),应当可以看见nginx的欢迎信息。

 

为了与uWSGI连接,需要一个uwsgi_params文件和一个nginx的conf文件。uwsgi_params文件可以从如下地址获取。

https://github.com/nginx/nginx/blob/master/conf/uwsgi_params

其内容为

 

uwsgi_param  QUERY_STRING       $query_string;
uwsgi_param  REQUEST_METHOD     $request_method;
uwsgi_param  CONTENT_TYPE       $content_type;
uwsgi_param  CONTENT_LENGTH     $content_length;

uwsgi_param  REQUEST_URI        $request_uri;
uwsgi_param  PATH_INFO          $document_uri;
uwsgi_param  DOCUMENT_ROOT      $document_root;
uwsgi_param  SERVER_PROTOCOL    $server_protocol;
uwsgi_param  REQUEST_SCHEME     $scheme;
uwsgi_param  HTTPS              $https if_not_empty;

uwsgi_param  REMOTE_ADDR        $remote_addr;
uwsgi_param  REMOTE_PORT        $remote_port;
uwsgi_param  SERVER_PORT        $server_port;
uwsgi_param  SERVER_NAME        $server_name;

将该uwsgi_params文件复制到Django project的文件夹,即

 

 

/home/yaoyu/MySites/uwsgi-tutorial/mysite

 

并在同样位置创建mysite_nginx.conf文件,内容为

 

# mysite_nginx.conf

# the upstream component nginx needs to connect to
upstream django {
    # server unix:///home/yaoyu/MySites/uwsgi_tutorial/mysite/mysite.sock; # for a file socket
    server 127.0.0.1:8001; # for a web port socket (we'll use this first)
}

# configuration of the server
server {
    # the port your site will be served on
    listen      8000;
    # the domain name it will serve for
    server_name .example.com; # substitute your machine's IP address or FQDN
    charset     utf-8;

    # max upload size
    client_max_body_size 75M;   # adjust to taste

    # Django media
    location /media  {
        alias /home/yaoyu/MySites/uwsgi-tutorial/mysite/media;  # your Django project's media files - amend as required
    }

    location /static {
        alias /home/yaoyu/MySites/uwsgi-tutorial/mysite/static; # your Django project's static files - amend as required
    }

    # Finally, send all non-media requests to the Django server.
    location / {
        uwsgi_pass  django;
        include     /home/yaoyu/MySites/uwsgi-tutorial/mysite/uwsgi_params; # the uwsgi_params file you installed
    }
}

mysite_nginx.conf文件的内容包括上游数据源的描述,目前为localhost:8001,nginx监听8000端口向client提供web服务,server的media文件位置以及static文件位置,最后是这个server的根位置。将mysite_nginx.conf以符号连接的形式插入到nginx的默认服务器列表里。

 

 

sudo ln -s /home/yaoyu/MySites/uwsgi-tutorial/mysite/mysite_nginx.conf /etc/nginx/sites-enabled/

 

收集Django project的static文件。修改/home/yaoyu/MySites/uwsgi-tutorial/mysite/mysite/settings.py,添加如下一行

 

STATIC_ROOT = os.path.join(BASE_DIR, "static/")

然后执行

python manage.py collectstatic

将自动生成一个新文件夹static。启动nginx进行测试

 

 

sudo /etc/init.d/nginx restart

 

此时由于没有任何实际server在运行,于是访问localhost:8000是显示Bad Geteway。但是仍可以测试nginx的运行。在

 

/home/yaoyu/MySites/uwsgi-tutorial/mysite

 

下新建media文件夹,进入media文件夹,并复制一个png图片进来,然后利用localhost:8000/media/文件名.png的形式通过浏览器查看这个图片,若成功显示图片,代表nginx的配置是正确的。
 

nginx,uWSGI和Django联调

 

首先通过uwsgi和test.py还有nginx进行联调。在

 

/home/yaoyu/MySites/uwsgi-tutorial/mysite

 

运行

 

uwsgi --socket :8001 --wsgi-file test.py

 

此时通过浏览器访问localhost:8000,此时应有Hello world字样。uwsgi通过localhost的8001端口向nginx提供数据,nginx再通过localhost的8000端口向浏览器提供数据。用Ctrl+C退出uwsgi。

 

现在利用Unix socket代替TCP端口。上面的测试使用的是8001端口,通过修改mysite_nginx.conf中upstream django中的描述(即将原来注释掉的socket描述恢复,而注释8001端口的描述。)再重启nginx服务

 

sudo /etc/init.d/nginx restart

 

另外,在Ubuntu系统上,nginx服务是默认已www-data用户和www-data用户组启动的。这里可以将当前用户添加至www-data用户组

 

sudo usermod -a -G www-data yaoyu

 

可能需要重新登录。之后可利用group或者id命令查看。

 

启动uwsgi

 

uwsgi --socket mysite.sock --wsgi-file test.py --chmod-socket=664 --chown-socket=yaoyu:www-data

 

推荐此时再另开一个Terminal,并输出nginx的error log

 

tail -f /var/log/nginx/error.log

 

通过浏览器访问localhost:8000,此时若出现Bad Gateway错误,并且nginx的error log提示Permission denied或connection refused。这表示nginx没有对mysite.sock文件的操作权限(仅限Ubuntu系统,对于CentOS或者Fedora可能是与SELinux有关)。处理方案是采用tmpfiles.d,可参考

https://www.freedesktop.org/software/systemd/man/tmpfiles.d.html

方案原理是将socket文件放置在一个nginx和uWSGI都有足够权限的位置,比较理想的位置是/run(或者其变种/var/run),在/run下建立一个文件夹位置,并设定该文件夹的权限。具体做法是在/etc/tmpfiles.d下新建一个conf文件,这里我们用mysite-socket.conf命名,其内容为

 

# Create directory for my sites.

d /run/mysite-socket 0775 www-data www-data -

这表示建立/run/mysite-socket 文件夹,并设定好权限位以及所有者和所有群,并不设定过期清空时间。

 

然后,修改mysite_uwsgi.conf的描述,将socket文件指向于/run/mysite-socket文件夹内。重启计算机。之后查看/run的内部是否有mysite-socket文件夹,并确认它的权限位和所有者情况。


调试成功后进行Django的联调。通过Ctrl+C退出uWSGI,在

 

/home/yaoyu/MySites/uwsgi-tutorial/mysite

 

重新启动uWSGI

 

uwsgi --socket /run/mysite-socket/mysite.sock --module mysite.wsgi --chmod-socket=664 --chown-socket=yaoyu:www-data

 

在浏览器中访问localhost:8000应当可以看到Django的信息。用Ctrl+C退出uWSGI。

 

为了避免使用命令启动uWSGI并实现自动化启动uWSGI,编写uWSGI的ini文件。命名为mysite_uwsgi.ini

 

# mysite_uwsgi.ini file
[uwsgi]

# Django-related settings
# the base directory (full path)
chdir           = /home/yaoyu/MySites/uwsgi-tutorial/mysite

# Django's wsgi file
module          = mysite.wsgi

# the virtualenv (full path)
home            = /home/yaoyu/MySites/uwsgi-tutorial

# process-related settings
# master
master          = true

# maximum number of worker processes
processes       = 10

# the socket (use the full path to be safe
socket          = /home/yaoyu/MySites/uwsgi-tutorial/mysite/mysite.sock

# ... with appropriate permissions - may be needed
chmod-socket    = 664
chown-socket    = yaoyu:www-data

# clear environment on exit
vacuum          = true

 

 

使用ini文件启动uWSGI

 

 

uwsgi --ini mysite_uwsgi.ini

 

同样通过浏览器访问localhost:8000,成功后终止uWSGI。

在virtualenv外安装调试uWSGI

为了能够部署服务器,uWSGI不能仅运行在virtualenv中,需要在其外也能够正常运行。

 

以上的调试工作实际上完全在uwsgi-tutorial virtualenv中进行的,现在退出该virtualenv。执行

 

deactivate

 

安装uWSGI

 

sudo pip3 install uwsgi

 

安装完毕后,在

 

/home/yaoyu/MySites/uwsgi-tutorial/mysite

 

下测试uWSGI

 

uwsgi --ini mysite_uwsgi.ini

 

通过浏览器访问localhost:8000,应看到Django信息。用Ctrl+C退出uWSGI。

 

uWSGI的emperor mode

运行于emperor mode下的uWSGI,可以通过监视conf文件的变化,重新启动服务。emperor mode需要使用uWSGI的vassal文件夹进行配置,新建

 

/etc/uwsgi/vassals (需要root权限)

 

在该文件夹下添加符号连接

 

sudo ln -s /home/yaoyu/MySites/uwsgi-tutorial/mysite/mysite_uwsgi.ini /etc/uwsgi/vassals/

 

以emperor mode启动uWSGI

 

sudo uwsgi --emperor /etc/uwsgi/vassals --uid yaoyu --gid www-data

 

利用浏览器访问localhost:8000,应可看到Django信息。利用Ctrl+C退出uWSGI(emperor mode)。

 

配置uWSGI随系统启动

配置/etc/rc.local文件(需要root权限),将上述uWSGI的emperor mode启动命令添加到rc.local文件的exit 0前。(貌似不加uid和gid也可以。)

 

/usr/local/bin/uwsgi --emperor /etc/uwsgi/vassals --uid yaoyu --gid www-data --daemonize /var/log/uwsgi-emperor.log


保存文件,重新启动系统。重新启动之后,直接通过浏览器访问localhost:8000,应当可以看到Django信息。

 

总结

多看官方网页,多用google,耐心不要急。初期尽量使用源,而不要自己编译python3什么的,别说我没提醒过。。。

 

 

 

你可能感兴趣的:(django,python,移动App)