Django部署完全指南(django+nginx+uwsgi)

接触Django,第一次撞墙了。google、百度了一晚上才搞明白。虽然python、django火了好几年,讲部署的文不少。很多博主都身经百战,对我这种小白,很多细节没有说到。这里把自己遇到的坑,以及部署的方法,整理出来,仅供参考。 在linux上搭建django部署环境,折腾了好几个小时。nginx、firewall、iptables、uwsgi一个个都不让人省心。

接触Django,第一次撞墙了。google、百度了一晚上才搞明白。虽然python、django火了好几年,讲部署的文不少。很多博主都身经百战,对我这种小白,很多细节没有说到。这里把自己遇到的坑,以及部署的方法,整理出来,仅供参考。 在linux上搭建django部署环境,折腾了好几个小时。nginx、firewall、iptables、uwsgi一个个都不让人省心。

这篇文章重点说明uwsgi与nginx的配置,至于其他,之后有时间在单独写出来,整合到这里。

网上关于django部署的文章不少,看多了难免有雷同的地方。后面的文,我尽量将自己遇到的难点写出来。不详尽的地方欢迎指出,欢迎加QQ群(709904667)讨论。

部署环境准备工作

如果使用mac电脑开发,建议在不了解部署wsgi的时候,先在本地进行uwsgi的部署测试。 我使用的开发环境OS 10.13.3 (17D47)。部署环境Centos 7.2。部署环境准备,当然要装好python(python3.6)、pip3、nginx、django。关闭firewall,安装iptables并开放80端口,以及用于django测试的端口(这里使用8000)。具体怎么做百度、google,或者等本懒哪天整理出来放到这里。(笑~)

Centos 7.2下安装python3一定会遇到yum异常的问题,记得修复一下,以防以后安装时懵逼,参考vi /usr/bin/yum,将第一行改为#!/usr/bin/python2.7。python版本号看一下自己本机的python2版本号。

Centos 自带的firewall用得不习惯,以前也一直用的iptabls,果断换掉。

做完以上工作,浏览器访问服务器可以看到nginx的默认页面,就算成功了。祝你幸福~

WSGI二三事

想通过nginx部署django,随便搜一下,都能看到一个叫做uwsgi的程序。uwsgi是什么鬼?为啥不能像平时runserver直接运行,然后用nginx做个端口转发?

说到这里,就要先说明一下大多将python作为第二开发语言的人忽略的一个知识点——python 中的 WSGI,官方描述点这里PEP 3333WSGI(the Python Web Server Gateway Interface)最开始就是python中为了规范web服务开发定义的标准。作为一套标准接口,我们在这里只需要了解它的实现之一——Django! Django实现了WSGI中定义的规范,可以监听端口,并返回对应的消息。所以我们才能通过python manage.py runserver启动一个http服务。

本文提到的uwsgi,是一种实现了WSGI协议的服务器。我们这里可以使用uwsgi直接对接python程序实现http服务,也可以通过(重点)uwsgi调用django中WSGI的实现,搭建与nginx通信的桥梁。

之后的两个小节,将介绍uwsgi的安装、测试、以及调起django的方法。

uwsgi安装与测试

上面说了那么多,其实有pip的帮助,安装uwsgi非常容易,一句代码搞定

pip install uwsgi

这一步不会报错,除非pip没有正确安装。另外不要用yum或apt-get命令安装,否则运行时得加很多参数。

搬一下砖,测试uwsgi的方法如下:

1、编写测试文件uwsgi_test.py,代码如下:

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

2、使用uwsgi启动python web服务

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

3、浏览器输入:http://127.0.0.1:8000,是不是看到亲切的Hello World了?什么没看到?换个端口试试,并检查uwsgi安装。

特别说明:uwsgi执行时,如果应为程序或者配置问题,导致启动失败,很容易造成端口被占用,而且很难杀死。测试的时候请及时更换端口,避免浪费时间。

uwsgi运行django

注意:这里可能会遇到很多问题,这里只说明必要操作。 有些关于uwsgi的说明中,让改django中的一个wsgi.py的文件。这里我要说django中,什么都不需要改。什么都不需要改!!! 另外有一些文中,uwsgi启动django的命令很复杂,类似上面uwsgi --http :8000 --wsgi-file uwsgi_test.py这种。不需要!!! 我们只需要一个简单的配置文件,在网站项目根目录新建uwsgi.ini,官方给出django的最简配置如下:

[uwsgi]
socket = 127.0.0.1:3031
chdir = /home/foobar/myproject/
wsgi-file = myproject/wsgi.py
processes = 4
threads = 2
stats = 127.0.0.1:9191

将本网站的配置拿出来分享下:

[uwsgi]
# socket = /zcm_web/zcm_blog/zcm_blog.sock
socket = 0.0.0.0:8001
master = true
chdir = /zcm_web/zcm_blog/
processes = 4
threads = 2
vacuum = true
pidfile = /zcm_web/zcm_blog/uwsgi.pid
wsgi-file = /zcm_web/zcm_blog/wsgi.py
daemonize = /zcm_web/zcm_blog/uwsgi.log

里面参数都是干什么的呢?请看官方说明。本懒才不会翻译呢~

简单说一下用到的参数:

socket:用于和nginx通信的端口设置。看官网意思是,这里可以是一个sock文件,因为本懒没用过,所以简单配置了一个端口供nginx桥接。

master:enable master process,主控程序可用?不知道什么鬼,以前间别人的配置文件有,貌似就加上了。

chdir:设置网站目录

processes:进程数,具体效果没有确定

threads:线程数,具体效果没有确定

vacuum:真空,嗯,一定是个好参数,加上。设置为true会在退出是,删除pid和socket文件。我这里只确认了对pid有效(因为没有用socket文件嘛)。 下面3个参数是重点,一定要配置对了

pidfile:pid文件位置,我直接指定到web根目录。uwsgi启动时会创建pid文件,用于uwsgi的重启和关闭。

wsgi-file:指定django的wsgi.py文件所在位置。

daemonize:指定log目录,不然哪里出错了都不知道。

配置成功之后,到网站根目录,输入 uwsgi uwsgi.ini测试直接访问服务器该端口,不出问题的话应该可以访问了。有问题来群里讨论一下~

特别说明:因为我使用的域名测试,需要在setting.py中修改ALLOWED_HOSTS,不然没法访问。里面默认只有localhost

nginx配置

如果说上面uwsgi已经正确配置,那么接下来就是让nginx可以将请求转发到uwsgi了。我使用的本文为nginx 1.12.2,配置上推荐一下文件结构:

nginx
|
-conf.d   #文件夹
  |
  -zcm_blog.conf
-nginx.conf
-其他文件

配置nginx.conf,在里面读取conf.d中的配置文件。这样每次新增网站或者服务,只需要在conf.d中增加一个文件,不必改动已有文件。 这里给出我的配置,nginx.conf:

# For more information on configuration, see:
#   * Official English Documentation: http://nginx.org/en/docs/
#   * Official Russian Documentation: http://nginx.org/ru/docs/

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf;

    server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  _;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location / {
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }

# Settings for a TLS enabled server.
#
#    server {
#        listen       443 ssl http2 default_server;
#        listen       [::]:443 ssl http2 default_server;
#        server_name  _;
#        root         /usr/share/nginx/html;
#
#        ssl_certificate "/etc/pki/nginx/server.crt";
#        ssl_certificate_key "/etc/pki/nginx/private/server.key";
#        ssl_session_cache shared:SSL:1m;
#        ssl_session_timeout  10m;
#        ssl_ciphers HIGH:!aNULL:!MD5;
#        ssl_prefer_server_ciphers on;
#
#        # Load configuration files for the default server block.
#        include /etc/nginx/default.d/*.conf;
#
#        location / {
#        }
#
#        error_page 404 /404.html;
#            location = /40x.html {
#        }
#
#        error_page 500 502 503 504 /50x.html;
#            location = /50x.html {
#        }
#    }

}

zcm_blog.conf配置如下:

  server {
    listen       80 ;
    server_name  www.imzcm.com;

    location / {
        include uwsgi_params;
        uwsgi_pass 127.0.0.1:8001;
    }
    location /static/ {
        root /zcm_web/zcm_blog/;
    }

    error_page 404 /404.html;
        location = /40x.html {
    }

    error_page 500 502 503 504 /50x.html;
        location = /50x.html {
    }
}

这些配置用了3年了,稳稳的。 zcm_blog.conf中uwsgi_pass用于指定uwsgi启动的端口,要与之前配置文件中的socket保持一致~

配置之后执行nginx -s reload加载配置,nginx不报错的话,就可以访问django网站了。

特别说明:配置中发现比较容易出错的地方,为uwsgi.ini配置和zcm_blog.conf配置。先使用ip调试,没问题之后使用域名测试。

就到这里,在部署中挣扎的朋友要加油了~


作者

NewImaging
  • Shadust
  • 有你,真好~

评论