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
的方式