dongnan
总版主
总版主
  • 粉丝52
  • 发帖数2165
  • 铜币13236枚
  • 威望5838点
  • 银元150个
  • 社区居民
  • 最爱沙发
  • 忠实会员
  • 原创写手
阅读:259回复:0

如何在容器中使用 Nginx & Gunicorn 管理Django 应用?

楼主#
更多 发布于:2018-06-21 15:24
目标
基于 python:3 Docker 基础镜像,使用 Nginx & Gunicorn 管理 Django web应用程序,并封装成新的 Django 镜像。

方案
1. 使用 supervisor 来管理 gunicorn 与 Nginx 。
2. 使用 gunicorn 来管理 django 应用程序,实现管理多个 worker 进程。
3. 使用 nginx 反向代理 django应用程序,实现web 动/静态资源分离

环境
应用程序及环境请参考 , 如何自定义 Django Docker镜像

问题
1. 为什么使用 Gunicorn 管理 Django 应用程序?
Gunicorn 是一个高效的 Python WSGI Server,通常用来管理多个进程,有进程挂了Gunicorn 可以把它拉起来,防止服务器长时间停止服务,还可以动态调整 worker 的数量,请求多的时候增加 worker 的数量,请求少的时候减少。

2. 为什么使用 Nginx 反向代理 Django web应用程序?
当访问一个页面时,服务器会接收到两种不同类型请求:
2.1 文章的详情信息,需要调用数据库获取数据。
2.2 图片、css、js、html 等静态文件。

对于第一种请求,博客文章的数据需要借助 Django 从数据库中获取,Nginx 处理不了它就会把这个请求转发给 Django,让 Django 去处理。
对于第二种请求,只需要去这些静态文件所在的文件夹获取,Nginx 就会代为处理,不再麻烦 Django。

相比 Django 框架内置的 Web服务器,Nginx 可以更高效的处理静态文件请求,因此生产环境推荐使用 Nginx + Django 的方式。

部署
1. 目录结构
tree -L 1 gunicorn/
gunicorn/
├── conf
├── django-blog-tutorial
└── Dockerfile

2 directories, 1 file

2. Dockerfile 文件
# 注意,Dockerfile 中并没有单独的命令来安装 gunicorn ,而是将 gunicorn 定义在 requirements.txt 文件中。
cat gunicorn/Dockerfile
# django-blog

FROM python:3
MAINTAINER dongnan <http://zongming.net>

# apt
COPY conf/sources.list /etc/apt/sources.list
RUN apt-get update \
    && apt-get install -y supervisor nginx \
    && apt-get clean \
    && rm -r /var/lib/apt/lists/*

# env
ENV TZ=Asia/Shanghai \
    LANG=en_US.UTF-8

# workdir
COPY django-blog-tutorial /code/
WORKDIR /code

# nginx
COPY conf/nginx.conf /etc/nginx/nginx.conf
COPY conf/default.conf /etc/nginx/conf.d/default.conf

# django dependents
RUN pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/
RUN python manage.py collectstatic -l --noinput \
    && python manage.py migrate
RUN echo "from django.contrib.auth.models import User; User.objects.create_superuser('admin', 'admin@demo.com', 'test666')" | python manage.py shell

# supervisor
COPY conf/supervisord.conf /etc/supervisor/supervisord.conf
CMD ["/usr/bin/supervisord","-c","/etc/supervisor/supervisord.conf"

3. nginx 配置文件
cat gunicorn/conf/default.conf
server {

    listen      80;
    server_name  zongming.net;
    #root  /var/www/html/bbs;
    error_page 404 /404.html;
  
    location ^~ /static {
        expires      30d;
        alias /code/static/;
    }

    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_set_header Host $host;
        # we don't want nginx trying to do something clever with
        # redirects, we set the Host: header above already.
        proxy_redirect off;
        proxy_pass http://unix:/var/run/django.socket;
    }

    access_log  /var/log/nginx/access.log access;
    error_log  /var/log/nginx/error.log;
}

4. 创建镜像
docker build -t gunicorn:0.0.1 .
Sending build context to Docker daemon  774.7kB
Step 1/14 : FROM python:3
 ---> 29d2f3226daf
Step 2/14 : MAINTAINER dongnan <http://zongming.net>
 ---> Using cache
...省略
Step 14/14 : CMD ["/usr/bin/supervisord","-c","/etc/supervisor/supervisord.conf"]
 ---> Running in 1f325a2c1ddd
Removing intermediate container 1f325a2c1ddd
 ---> cd2a8533ab3d
Successfully built cd2a8533ab3d
Successfully tagged gunicorn:0.0.1

5. 创建容器
docker run --name test -tid gunicorn:0.0.1
66655a0cff8b408cbe75d1ac71cde4e0cac60b13b862f59ce1cd14d03e606581

验证
1. 容器进程日志
docker logs test
2018-06-19 14:17:10,473 CRIT Supervisor running as root (no user in config file)
2018-06-19 14:17:10,480 INFO supervisord started with pid 1
2018-06-19 14:17:11,482 INFO spawned: 'nginx' with pid 7
2018-06-19 14:17:11,485 INFO spawned: 'gunicorn' with pid 8
2018-06-19 14:17:12,884 INFO success: nginx entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
2018-06-19 14:17:12,885 INFO success: gunicorn entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)

2. 访问 Web服务
curl -H "Host:zongming.net" -IL 192.168.0.2
HTTP/1.1 200 OK
Server: nginx
Date: Thu, 19 Jun 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


参考
How to use Django with Gunicorn
Gunicorn
Deploying Gunicorn
使用 Nginx 和 Gunicorn 部署 Django 博客
如何自定义 Django Docker镜像?
#
游客

返回顶部