Django容器(下): 使用Gunicorn管理Django
- 2019 年 12 月 19 日
- 筆記
开始之前
在上一篇文章《Django容器(上): 自定义基础镜像》我们已经封装好了Django
项目的基础镜像,接下来需要在基础镜像之上做些收尾工作,主要以下几点:
- 在基础镜像中加入项目代码。
- 配置
Gunicorn
管理 Django 应用。 - 配置
Supervisor
管理 Nginx 与 Gunicorn进程。
一些问题
为什么使用 Gunicorn 管理 Django 应用?
Gunicorn
(Green Unicorn)是一个高效的 Python WSGI Server
,常用来管理多个进程。
如果有进程挂了Gunicorn
可以把它启动起来,防止长时间停止服务。
此外 Gunicorn
还可以动态调整 worker
的数量,请求多时增加 worker
的数量,相反则减少。
为什么使用 Nginx 代理 Gunicorn 应用?
当访问网站时,服务器会接收到不同类型的资源请求:a. Pic、Css、Js 等静态资源文件。b. 详情页等需要调用数据库动态获取的数据。
对于动态数据请求,文章数据需要 Django 从数据库中获取。Nginx
会把这个请求转发给 Django
处理。
对于静态资源请求,只需要 Nginx 去项目所在的目录直接获取,不再麻烦Django
。
相比 Django
框架内置的Web服务器,Nginx
可以更高效的处理静态文件请求。
因此生产环境推荐使用 Nginx + Gunicorn + Django
的方式。
梳理一下本项目中进程关系
使用 `supervisor` 来管理 'gunicorn' 与 'Nginx'进程。 使用 `gunicorn` 来管理 'django'应用,实现管理多个'worker'进程。 使用 `nginx` 反向代理 'gunicorn' 应用,实现"动/静态分离"。
操作步骤
1. 项目镜像构建目录
tree -L 1 ./ ./ ├── base # 基础镜像目录 ├── Dockerfile # 项目 Dockerfile └── start # 项目代码目录 2 directories, 1 file
2. Dockerfile 文件
cat Dockerfile # use start-base image FROM start-base # nginx COPY base/conf/nginx.conf /etc/nginx/nginx.conf COPY base/conf/default.conf /etc/nginx/conf.d/default.conf COPY base/conf/ssl /etc/nginx/ssl # django COPY start /start WORKDIR /start # 收集静态文件到 STATIC_ROOT 中,项目中为 /start/static RUN python manage.py collectstatic -l --noinput # supervisor COPY base/conf/supervisord.conf /etc/supervisor/supervisord.conf CMD ["/usr/bin/supervisord","-c","/etc/supervisor/supervisord.conf"]
相关命令可以参考 《如何使用 Dockerfile自定义镜像?》 这篇文章。
3. supervisor 配置文件
cat base/conf/supervisord.conf [supervisord] nodaemon=true pidfile=/var/run/supervisord.pid logfile=/var/log/supervisor/supervisord.log [program:nginx] command=/usr/sbin/nginx -g "daemon off;" [program:gunicorn] command=gunicorn -w 2 -b unix:/var/run/django.socket web.wsgi:application stderr_logfile=/var/log/gunicorn.stderr stdout_logfile=/var/log/gunicorn.stdout
supervisor 配置可以参考《为什么需要自定义一个基础镜像? 》 这篇文章。gunicorn 选项请参考下面。
4. nginx 配置文件
cat base/conf/default.conf server { listen 80; listen 443 ssl; server_name www.zongming.net; # 其它配置项省略... # 保持与 django MEDIA_URL 一致 location ^~ /attachments { alias /start/uploads/; expires 180d; } # 保持与 django STATIC_URL 一致 location ^~ /static { root /start/; expires 180d; } location / { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Host $http_host; proxy_pass http://unix:/var/run/django.socket; proxy_redirect default; } access_log /var/log/nginx/access.log access; error_log /var/log/nginx/error.log; }
注意,proxy_pass
代理的 sokect
文件路径,与 supervisor
中保持一致。
nginx 代理配置项可以参考《Nginx Proxy 反向代理》 这篇文章。
5. 构建项目镜像
docker build -t start:0.0.1 . Sending build context to Docker daemon 3.5mb Step 1/9 : FROM python:3 # ...省略 Successfully built cd2a8533ab3d Successfully tagged start:0.0.1
6. 验证django容器
a. 创建容器
docker run --name test -d start:0.0.1 66655a0cff8b#省略..2f59ce1cd14d03e606581
b. 容器进程
pstree 15585 supervisord─┬─gunicorn───2*[gunicorn] └─nginx───nginx
c. 访问服务
curl www.demo.com HTTP/1.1 200 OK Server: nginx Date: Thu, 19 Jan 2018 04:37:12 GMT Content-Type: text/html; charset=utf-8 Connection: keep-alive Keep-Alive: timeout=10 Vary: Accept-Encoding X-Frame-Options: SAMEORIGIN
命令帮助
语法: gunicorn [OPTIONS] APP_MODULE 示例: gunicorn -w 2 -b unix:/var/run/django.socket web.wsgi:application `web` 为 django项目应用名称,例如示例中的 Django工程是使用以下命令创建的。 # 创建 start 项目 django-admin startproject start # 创建 web 应用 python manage.py startapp web 选项 -b BIND 指定要绑定的服务器套接字。服务器套接字可以是: `$(HOST)`, `$(HOST):$(PORT)`, `unix:$(PATH)`中的任何一个。IP 是有效的`$(HOST)`。 默认值为 ['127.0.0.1:8000'] -w WORKERS 处理请求的工作进程数。此值通常应为服务器中每个核心(CPU) 2-4之间,默认值为1。
小结
最后来总结下文章中的知识点
- 使用
supervisor
在 docker 容器中管理nginx、gunicorn
进程。 Gunicorn
是一个高效的Python WSGI Server
,常用来管理多个进程。- 对于
django
项目,推荐生产环境使用Nginx + Gunicorn + Django
的方式