使用Nginx和Gunicorn运行Django

虽然 运行Django 非常简单,能够快速完成开发工作。但是对于生产环境,显然不能仅仅使用Django运行在8000端口对外提供服务,因为Django内建的简单的开发服务器仅适合本地测试代码,在生产环境需要更为安全和强大的WEB服务器。

Gunicom ( Green Unicorn ) 是一个纯Python WSGI,可以通过 pip 安装,结合 Nginx反向代理,可以提供安全和高性能的WEB服务。

安装Gunicorn

Gunicorn是一个纯Python程序,安装通过 pip 非常简单:

python -m pip install gunicorn

作为通用WSGI应用在Gunicorn中运行Django

  • gunicorn 命令可以启动 Gunicorn服务集成,最简单的就是在项目目录下以项目名称运行:

    gunicorn myproject.wsgi
    

上述命令会在 127.0.0.1:8000 上监听一个进程。

  • 比较常用的命令方法如下:

    gunicorn --bind 0.0.0.0:8000 myproject.wsgi
    

这样我们就可以配置nginx来作为反向代理访问服务了。

  • 要启动多个进程,可以增加 workers 参数,例如运行3个进程:

    gunicorn --bind 0.0.0.0:8000 --workers=3 myproject.wsgi
    
  • 如果要通过本地socket访问wsgi加速性能,运行unicorn时指定socket位置(这里假设运行用户账号是 admin ):

    sudo mkdir /run/gunicorn
    sudo chown admin:admin /run/gunicorn
    gunicorn --bind unix:/run/gunicorn/gunicorn.sock --workers=3 myproject.wsgi
    

配置systemd运行gunicorn

为了方便运行 gunicorn ,最好是配置 systemd 这样的进程管理器来实现服务起停。

  • 创建 /etc/systemd/system/gunicorn.socket

nginx_gunicorn_django/gunicorn.socket
1[Unit]
2Description=gunicorn socket
3
4[Socket]
5ListenStream=/run/gunicorn/gunicorn.sock
6
7[Install]
8WantedBy=sockets.target
  • 创建 /etc/systemd/system/gunicorn.service

nginx_gunicorn_django/gunicorn.service
 1[Unit]
 2Description=gunicorn daemon
 3Requires=gunicorn.socket
 4After=network.target
 5
 6[Service]
 7User=sammy
 8Group=www-data
 9WorkingDirectory=/home/admin/onesre
10ExecStart=/home/admin/venv3/bin/gunicorn \
11          --access-logfile - \
12          --workers 3 \
13          --bind unix:/run/gunicorn/gunicorn.sock \
14          onesre.wsgi
15
16[Install]
17WantedBy=multi-user.target
  • 然后激活socket:

    sudo systemctl start gunicorn.socket
    sudo systemctl enable gunicorn.socket
    
  • 上述配置中, gunicorn.service 会在 gunicorn.socket 激活后启动,所以需要连接一次本地socket:

    curl --unix-socket /run/gunicorn/gunicorn.sock localhost
    

然后检查服务:

sudo systemctl status gunicorn

就会看到gunicorn服务已经启动。

  • 激活服务:

    sudo systemctl daemon-reload
    sudo systemctl restart gunicorn
    

配置Nginx反向代理到Gunicorn

  • 在CentOS 7上安装Nginx需要先安装EPEL:

    sudo yum install epel-release
    
  • 然后安装Nginx:

    sudo yum install nginx
    
  • 检查 /etc/nginx/nginx.conf 查看配置默认会包含哪些配置目录,有的配置版本是包含 /etc/nginx/sites-available/ ,有的则是包含 /etc/nginx/conf.d/ 目录。在配置目录下添加项目配置 onesre-core.conf (案例项目名)

nginx_gunicorn_django/onesre-core.conf
 1server {
 2    listen 80;
 3    server_name onesre.huatai.me;
 4    root         /usr/share/nginx/html;
 5
 6    location = /favicon.ico { access_log off; log_not_found off; }
 7    location /static/ {
 8        alias /home/admin/onesre/core/staticfiles/;
 9    }
10
11    location /api/ {
12        include proxy_params;
13        proxy_pass http://unix:/run/gunicorn/gunicorn.sock;
14    }
15}

上述配置中引用了 proxy_params 可能在某些早期版本nginx中没有包含,参考 Setup nginx Reverse Proxy :

nginx_gunicorn_django/proxy_params
 1proxy_set_header Host $host;
 2proxy_set_header X-Real-IP $remote_addr;
 3proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 4client_max_body_size 100M;
 5client_body_buffer_size 1m;
 6proxy_intercept_errors on;
 7proxy_buffering on;
 8proxy_buffer_size 128k;
 9proxy_buffers 256 16k;
10proxy_busy_buffers_size 256k;
11proxy_temp_file_write_size 256k;
12proxy_max_temp_file_size 0;
13proxy_read_timeout 300;

备注

需要注意要点:

  • nginx的运行进程账号需要和Django进程账号、gunicorn运行账号相同,或者需要确保读写 socket 具备权限。推荐账号采用 /sbin/nologin 降低安全隐患

  • 启动nginx:

    sudo /usr/sbin/nginx
    

参考