python36 Django项目部署到uWSGI + Nginx 环境的笔记

1. 架构关系:

Nginx和uWSGI都是Web服务器,Nginx负责静态内容,uWSGI负责Python这样的动态内容,二者配合共同提供Web服务以实现提高效率和负载均衡等目的。

uWSGI实现了多个协议,如WSGI,HTTP协议,还有它自己的uwsgi协议,想了解更多关于uWSGI和uwsgi协议内容可以查阅这里。请求和响应的流程如下:

Request > Nginx > uWSGI > Django > uWSGI > Nginx > Response

2. 安装uWSGI:

pip3 install uwsgi

测试uwsgi是否可正常运行:

先定义一个test.py,内容如下:

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

再执行:uwsgi –http 127.0.0.1:9000 –wsgi-file test.py

如果浏览器访问: http://127.0.0.1:9000 能成功返回”Hello, Horkd”则表示uwsgi正常工作。否则还要再排查下安装过程。

网上很多文章在测试时写的return “Hello World”是错误的,在python3的环境下,用这条语句是不会把”Hello Horld”返回给前端页面的。

3.创建一个Django测试项目,名为pro:

cd /var/www/nginx-html/test/pro/

$django-admin startproject pro

cd /var/www/nginx-html/test/pro/pro

验证这个pro是否可以正常运行:

python manage.py runserver 0.0.0.0:8000

浏览器访问:   127.0.0.1:8000, 此时应能正常返回django欢迎页面。

4.用uwsgi加载django项目:

cd /var/www/nginx-html/test/pro

新建一个配置文件: uwsgi.ini, 内容为:

[uwsgi]
http=127.0.0.1:8000
#socket=/home/www/work/project/pro/nginx_uwsgi.socket
chdir=/var/www/nginx-html/test/pro
#chmod-socket=664
master=true
processes=4
threads=2
module=pro.wsgi
#wsgi-file=uwsgi_test.py
#stats=127.0.0.1:9000

执行命令加载django项目:
uwsgi –ini uwsgi.ini

另外一种运行方式:
# 进入这个django项目的根目录
cd /var/www/nginx-html/test/pro
# 使用--module参数
uwsgi --http :8000 --module pro.wsgi

浏览器访问:http://127.0.0.1:8000/

正常情况下应返回django的欢迎页面

(正式使用uwsgi时,可设置uwsgi为自启动)

5.部署nginx服务:

sudo yum install nginx

在启动nginx的时候经历了selinux限制导致无法正常启动的小插曲:

$ sudo service nginx start
Redirecting to /bin/systemctl start  nginx.service
Job for nginx.service failed because the control process exited with error code. See "systemctl status nginx.service" and "journalctl -xe" for details.
$ systemctl status nginx.service
● nginx.service - nginx - high performance web server
   Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled)
   Active: failed (Result: exit-code) since Sun 2018-09-09 23:15:30 CST; 9s ago
     Docs: http://nginx.org/en/docs/
  Process: 5410 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, status=1/FAILURE)

 SELinux is preventing /usr/sbin/nginx from name_bind access on the tcp_socket port 8081. For complete SELinux messages. run sealert -l 04b2ed94-23ec-4ed8-a29c
Sep 09 23:15:32 lanbaby.yichen python[5414]: SELinux is preventing /usr/sbin/nginx from name_bind access on the tcp_socket port 8081.
                                             
                                             *****  Plugin catchall (100. confidence) suggests   **************************
                                             
                                             If you believe that nginx should be allowed name_bind access on the port 8081 tcp_socket by default.
                                             Then you should report this as a bug.
                                             You can generate a local policy module to allow this access.
                                             Do
                                             allow this access for now by executing:
                                             # ausearch -c 'nginx' --raw | audit2allow -M my-nginx
                                             # semodule -i my-nginx.pp
                                             


#yum install policycoreutils-python
cat /var/log/audit/audit.log | grep nginx | grep denied | audit2allow -M my-nginx
semodule -i my-nginx.pp

$ sudo service nginx start
Redirecting to /bin/systemctl start  nginx.service
$ ps -ef |grep nginx
root      6709     1  0 23:44 ?        00:00:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
nginx     6710  6709  0 23:44 ?        00:00:00 nginx: worker process
lanbaby   6720  4605  0 23:44 pts/1    00:00:00 grep --color=auto nginx

cp /etc/nginx/uwsgi_params  /var/www/nginx-html/test/pro(备用)

cd /etc/nginx/conf.d (文件夹里的可以针对不同站点进行配置)

cp default.conf test-pro.conf (生成一个专门针对 test-pro 这个django项目的配置文件)

#nginx-pro
 
upstream django{
        server unix:///var/www/nginx-html/test/pro/nginx_uwsgi.sock; # file socket
        #server 127.0.0.1:7070; # TCP socket
}


server {
        listen 80 default_server;
        listen [::]:80 default_server;
        root /var/www/html;
        index index.html index.htm index.nginx-debian.html;
        server_name 127.0.0.1; # IP or FQDN

        location /static {
                alias /var/www/nginx-html/test/pro/static;
        }

        location / {
                uwsgi_pass django;
                include /var/www/nginx-html/test/pro/uwsgi_params;
                #try_files $uri $uri/ =404;
        }
}

这时配置都已完成,执行如下命令:

$uwsgi –ini uwsgi.ini
$sudo service nginx restart
这时会遇到下面报错:
SELinux is preventing /usr/sbin/nginx from read access on the file uwsgi_params.
SELinux is preventing /usr/sbin/nginx from open access on the file /var/www/nginx-html/test/prouwsgi_params.

$sudo cat /var/log/audit/audit.log | grep nginx | grep denied | audit2allow -M my-nginx
$sudo semodule -i my-nginx.pp
这时可以成功执行:
$sudo service nginx restart

这时访问 127.0.0.1:80,报错: 502 Bad Gateway

查看nginx错误日志,发现原因是没有权限访问文件:/var/www/nginx-html/test/pronginx_uwsgi.sock

$ sudo tail -f /var/log/nginx/error.log
[sudo] password for xxx: 
2018/09/09 23:14:21 [emerg] 5349#5349: bind() to 0.0.0.0:8081 failed (13: Permission denied)
2018/09/09 23:15:30 [emerg] 5410#5410: bind() to 0.0.0.0:8081 failed (13: Permission denied)
2018/09/09 23:49:26 [error] 6710#6710: *1 open() "/usr/share/nginx/html/favicon.ico" failed (2: No such file or directory), client: 127.0.0.1, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "127.0.0.1", referrer: "http://127.0.0.1/"
2018/09/10 00:25:28 [emerg] 8604#8604: open() "/var/www/nginx-html/test/prouwsgi_params" failed (13: Permission denied) in /etc/nginx/conf.d/test-pro.conf:22
2018/09/10 00:27:13 [emerg] 8679#8679: open() "/var/www/nginx-html/test/prouwsgi_params" failed (13: Permission denied) in /etc/nginx/conf.d/test-pro.conf:22
2018/09/10 00:29:21 [emerg] 8852#8852: open() "/var/www/nginx-html/test/prouwsgi_params" failed (13: Permission denied) in /etc/nginx/conf.d/test-pro.conf:22
2018/09/10 00:36:28 [crit] 8949#8949: *1 connect() to unix:///var/www/nginx-html/test/pronginx_uwsgi.sock failed (13: Permission denied) while connecting to upstream, client: 127.0.0.1, server: 127.0.0.1, request: "GET / HTTP/1.1", upstream: "uwsgi://unix:///var/www/nginx-html/test/pronginx_uwsgi.sock:", host: "127.0.0.1"
2018/09/10 00:36:36 [crit] 8949#8949: *1 connect() to unix:///var/www/nginx-html/test/pronginx_uwsgi.sock failed (13: Permission denied) while connecting to upstream, client: 127.0.0.1, server: 127.0.0.1, request: "GET / HTTP/1.1", upstream: "uwsgi://unix:///var/www/nginx-html/test/pronginx_uwsgi.sock:", host: "127.0.0.1"

 

 

 

 

 

参考资料:跨过Nginx上基于uWSGI部署Django项目的坑

使用nginx + uwsgi socket的方式来部署Django项目

Leave a Reply

Your email address will not be published.