Django 生產部署:Nginx + Gunicorn 完全指南 | Django 教學

2026/07/01 2026/05/27
Django 生產部署:Nginx + Gunicorn 完全指南 | Django 教學

從開發環境的 python manage.py runserver 到真正面對使用者的生產服務,中間隔著一道巨大的鴻溝。生產部署需要 Gunicorn 作為 WSGI(Web Server Gateway Interface) 應用伺服器來處理並發請求,再由 Nginx 擔任 反向代理(Reverse Proxy) 處理靜態檔案、SSL 終止與負載平衡。本篇將完整走過 Django 生產部署的標準架構,從安裝設定到上線檢查,帶你打造穩定高效的生產環境。

為什麼需要反向代理?

Django 內建的開發伺服器(runserver)是為了方便開發而設計的,它有幾個致命的限制:

特性開發伺服器(runserver)生產架構(Nginx + Gunicorn)
並發處理單執行緒,一次一個請求多 Worker 並發處理
靜態檔案效率極低,不支援快取Nginx 直接服務,支援快取與壓縮
SSL/TLS不支援Nginx 處理 SSL 終止
安全性無防護機制限制請求大小、防止慢速攻擊
程序管理無自動重啟Worker 崩潰自動重啟
效能僅供開發使用生產級效能

生產部署的標準架構如下:

Internet(使用者)
    ↓
[Nginx]  ← 靜態檔案服務、SSL 終止、反向代理
    ↓
[Gunicorn / Uvicorn]  ← WSGI/ASGI 應用伺服器,管理 Worker 程序
    ↓
[Django Application]  ← 業務邏輯處理
    ↓
[PostgreSQL] + [Redis]  ← 資料庫 + 快取

每一層各司其職:Nginx 處理網路層的事務,Gunicorn 管理應用程序,Django 專注於業務邏輯。


Gunicorn 安裝與基本設定

Gunicorn(Green Unicorn) 是 Python 生態系中最成熟的 WSGI HTTP 伺服器,採用 Pre-fork Worker Model(預先 fork 工作程序模型) ,在啟動時由 Master 程序預先 fork 出多個 Worker 程序,每個 Worker 獨立處理請求。

安裝 Gunicorn

# 安裝 Gunicorn
pip install gunicorn

# 確認安裝成功
gunicorn --version

基本啟動指令

# 最簡單的啟動方式
gunicorn myproject.wsgi:application

# 指定 Worker 數量與綁定位址
gunicorn myproject.wsgi:application --workers 4 --bind 0.0.0.0:8000

# 搭配常用參數
gunicorn myproject.wsgi:application \
  --workers 4 \
  --worker-class gthread \
  --threads 2 \
  --bind unix:/run/gunicorn.sock \
  --timeout 30

Gunicorn Worker 配置詳解

Worker 的配置直接影響應用的並發能力與資源使用效率,是 Gunicorn 調校的核心。

Worker 類型選擇

Worker 類型說明適用情境
sync(預設)同步 Worker,每個 Worker 一次處理一個請求一般 Django 應用、CPU 密集型任務
gthread多執行緒同步 WorkerI/O 等待較多的場景
gevent基於 gevent 的協程 Worker大量 I/O 等待、高並發連線
uvicorn.workers.UvicornWorkerASGI Worker,整合 Uvicornasync 視圖、WebSocket

Worker 數量建議

官方建議公式為 CPU 核心數 x 2 + 1

import multiprocessing

# 例如 4 核心伺服器:4 x 2 + 1 = 9 個 Workers
workers = multiprocessing.cpu_count() * 2 + 1

如果使用 gthread Worker,總並發量等於 workers x threads。例如 4 Workers 搭配 4 threads,可同時處理 16 個請求。

gunicorn.conf.py 設定檔

將所有設定集中到設定檔,便於版本控制與管理:

# gunicorn.conf.py
import multiprocessing

# === Worker 設定 ===
workers = multiprocessing.cpu_count() * 2 + 1  # Worker 數量
worker_class = 'sync'          # Worker 類型(預設同步)
threads = 2                    # 每個 Worker 的執行緒數
timeout = 30                   # Worker 靜默超時秒數(超時強制重啟)
graceful_timeout = 30          # 優雅關閉等待秒數
keepalive = 5                  # Keep-alive 連線秒數

# === 綁定設定 ===
bind = '0.0.0.0:8000'         # 綁定位址與端口

# === 日誌設定 ===
accesslog = '/var/log/gunicorn/access.log'   # 存取日誌路徑
errorlog = '/var/log/gunicorn/error.log'     # 錯誤日誌路徑
loglevel = 'info'                            # 日誌等級
access_log_format = '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s" %(D)s'

# === 安全設定 ===
limit_request_line = 4096      # 請求行最大長度
limit_request_fields = 100     # 請求標頭欄位最大數量

# === 程序管理 ===
pidfile = '/tmp/gunicorn.pid'  # PID 檔案路徑
daemon = False                 # 是否以 daemon 模式執行(使用 Systemd 時設 False)

使用設定檔啟動:

gunicorn myproject.wsgi:application -c gunicorn.conf.py

Nginx 反向代理設定

Nginx 是高效能的 HTTP 伺服器與反向代理伺服器,在 Django 生產架構中負責接收外部請求、服務靜態檔案、處理 SSL 終止,並將動態請求轉發給 Gunicorn。

安裝 Nginx

# Ubuntu / Debian
sudo apt update
sudo apt install nginx

# 啟動 Nginx
sudo systemctl start nginx
sudo systemctl enable nginx

完整 Nginx 設定檔

# /etc/nginx/sites-available/myapp.conf

# 定義上游 Gunicorn 伺服器
upstream django_app {
    server 127.0.0.1:8000;
    # 多個 Gunicorn 實例可做負載平衡
    # server 127.0.0.1:8001;
    # server 127.0.0.1:8002;
}

# HTTP → HTTPS 強制重導向
server {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;
    return 301 https://$host$request_uri;
}

# HTTPS 主設定
server {
    listen 443 ssl http2;
    server_name yourdomain.com www.yourdomain.com;

    # SSL 憑證設定(Let's Encrypt)
    ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    # 靜態檔案(直接由 Nginx 服務,不經過 Gunicorn)
    location /static/ {
        alias /var/www/myapp/staticfiles/;
        expires 30d;                              # 瀏覽器快取 30 天
        add_header Cache-Control "public, immutable";
    }

    # 媒體檔案
    location /media/ {
        alias /var/www/myapp/media/;
        expires 7d;
    }

    # 反向代理至 Gunicorn
    location / {
        proxy_pass http://django_app;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_read_timeout 90;
        proxy_connect_timeout 90;
        client_max_body_size 20M;   # 上傳檔案大小限制
    }
}

啟用站台設定

# 建立 symbolic link 啟用站台
sudo ln -s /etc/nginx/sites-available/myapp.conf /etc/nginx/sites-enabled/

# 測試設定檔語法
sudo nginx -t

# 重新載入 Nginx
sudo systemctl reload nginx

靜態檔案與媒體檔案服務

在生產環境中,靜態檔案不應該由 Django 處理,而是交給 Nginx 直接服務,效能差距可達數十倍。

收集靜態檔案

# 將所有靜態檔案收集到 STATIC_ROOT 目錄
python manage.py collectstatic --noinput
# settings.py(生產環境設定)
STATIC_URL = '/static/'
STATIC_ROOT = '/var/www/myapp/staticfiles/'   # collectstatic 輸出目錄

MEDIA_URL = '/media/'
MEDIA_ROOT = '/var/www/myapp/media/'          # 使用者上傳檔案目錄

靜態檔案服務策略比較

策略 1:Nginx 直接服務(最佳效能)
    → collectstatic → /var/www/myapp/staticfiles/ → Nginx location /static/
    適用:傳統伺服器部署

策略 2:WhiteNoise(簡化部署,無需額外 Nginx 設定)
    → WhiteNoise Middleware 直接從 Django 服務,支援 Gzip + ETag
    適用:PaaS 平台(Heroku、Render)

策略 3:CDN(全球分發,大流量首選)
    → collectstatic → 上傳 S3/GCS → CloudFront/Cloud CDN
    適用:全球用戶、高流量網站

Uvicorn 作為 ASGI 替代方案

如果你的 Django 專案使用了 非同步視圖(async def view)Django Channels(WebSocket) ,就需要 ASGI(Asynchronous Server Gateway Interface) 伺服器。 Uvicorn 是目前最受歡迎的 Python ASGI 伺服器,基於 uvloophttptools 構建,效能表現優異。

WSGI vs ASGI 選擇

特性WSGI(Gunicorn)ASGI(Uvicorn)
同步 View完整支援完整支援
非同步 View(async def)不支援支援
WebSocket不支援支援
成熟度非常成熟,生產首選較新,活躍發展中
推薦場景純 REST API、傳統 WebWebSocket、SSE、async I/O

安裝與啟動 Uvicorn

# 安裝 Uvicorn(含高效能依賴)
pip install uvicorn[standard]

# 開發環境啟動(自動重載)
uvicorn myproject.asgi:application --reload --host 0.0.0.0 --port 8000

生產環境:Gunicorn + UvicornWorker

在生產環境中,建議以 Gunicorn 作為程序管理器搭配 UvicornWorker,兼得兩者優勢:

# Gunicorn 管理 Uvicorn Worker
gunicorn myproject.asgi:application \
  -k uvicorn.workers.UvicornWorker \
  --workers 4 \
  --bind 0.0.0.0:8000

部署架構變為:

用戶端 → Nginx → Gunicorn(Master)→ UvicornWorker x N → Django ASGI

SSL/TLS 設定(Let’s Encrypt + Certbot)

Let’s Encrypt 提供免費的 SSL/TLS 憑證, Certbot 是其官方的自動化工具,能自動申請、安裝與續期憑證。

安裝 Certbot

# Ubuntu / Debian
sudo apt install certbot python3-certbot-nginx

申請憑證

# 自動為 Nginx 申請並設定 SSL 憑證
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com

# 或只申請憑證,手動設定 Nginx
sudo certbot certonly --webroot -w /var/www/myapp -d yourdomain.com

自動續期

Let’s Encrypt 憑證有效期為 90 天,Certbot 安裝後會自動設定定期續期:

# 測試自動續期
sudo certbot renew --dry-run

# 確認定時任務(systemd timer 或 cron)
sudo systemctl list-timers | grep certbot

Systemd 管理 Gunicorn

使用 Systemd 管理 Gunicorn 服務,可實現開機自動啟動、崩潰自動重啟與日誌整合。

建立 Gunicorn Socket 檔案

# /etc/systemd/system/gunicorn.socket
[Unit]
Description=Gunicorn Socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target

建立 Gunicorn Service 檔案

# /etc/systemd/system/gunicorn.service
[Unit]
Description=Gunicorn daemon for Django Application
Requires=gunicorn.socket
After=network.target

[Service]
User=www-data
Group=www-data
WorkingDirectory=/var/www/myapp
ExecStart=/var/www/myapp/venv/bin/gunicorn \
    --access-logfile - \
    --workers 4 \
    --bind unix:/run/gunicorn.sock \
    myproject.wsgi:application
Restart=on-failure
RestartSec=5s
Environment="DJANGO_SETTINGS_MODULE=myproject.settings.production"

[Install]
WantedBy=multi-user.target

啟動與管理

# 啟動 socket 與 service
sudo systemctl start gunicorn.socket
sudo systemctl enable gunicorn.socket

# 查看服務狀態
sudo systemctl status gunicorn

# 重新啟動(部署新版本後)
sudo systemctl restart gunicorn

# 查看日誌
sudo journalctl -u gunicorn --since today

部署前檢查清單

Django 提供了 check --deploy 指令,可以自動檢查常見的安全與設定問題:

# 執行部署檢查
python manage.py check --deploy

關鍵設定項目

# settings/production.py

# === 安全性 ===
DEBUG = False                       # 絕對不可為 True
SECRET_KEY = config('DJANGO_SECRET_KEY')  # 從環境變數讀取,不可寫死
ALLOWED_HOSTS = ['yourdomain.com', 'www.yourdomain.com']

# CSRF 信任來源(Django 4.0+ 必須包含 scheme)
CSRF_TRUSTED_ORIGINS = [
    'https://yourdomain.com',
    'https://www.yourdomain.com',
]

# === HTTPS 相關 ===
SECURE_SSL_REDIRECT = True          # HTTP 重導向至 HTTPS
SECURE_HSTS_SECONDS = 31536000      # HSTS 有效期一年
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
SESSION_COOKIE_SECURE = True        # Cookie 只透過 HTTPS 傳送
CSRF_COOKIE_SECURE = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

# === 靜態檔案 ===
STATIC_ROOT = '/var/www/myapp/staticfiles/'
MEDIA_ROOT = '/var/www/myapp/media/'

完整部署檢查清單

檢查項目說明
DEBUG = False生產環境必須關閉 Debug 模式
SECRET_KEY 從環境變數讀取不可寫死在程式碼中
ALLOWED_HOSTS 已設定防止 HTTP Host Header 攻擊
collectstatic 已執行靜態檔案已收集到 STATIC_ROOT
資料庫已 migrate確保資料庫 schema 為最新
SSL 憑證已安裝HTTPS 正常運作
Systemd service 已啟用Gunicorn 開機自動啟動
日誌路徑已建立Gunicorn 與 Nginx 日誌目錄存在且有寫入權限
防火牆已設定僅開放 80、443 port

總結

Django 生產部署是從開發走向上線的關鍵一步,正確的架構設定能確保應用的穩定性、安全性與效能。以下整理本篇的重點:

  1. 開發伺服器不可用於生產 ——runserver 缺乏並發處理、安全防護與效能最佳化,生產環境必須使用 Gunicorn 等專業應用伺服器
  2. Gunicorn Worker 配置 是效能調校的核心——Worker 數量建議為 CPU 核心數 x 2 + 1,搭配 gunicorn.conf.py 設定檔集中管理所有參數
  3. Nginx 反向代理 處理靜態檔案、SSL 終止與負載平衡——靜態檔案由 Nginx 直接服務,動態請求透過 proxy_pass 轉發給 Gunicorn
  4. Uvicorn 作為 ASGI 替代方案 ——當專案需要非同步視圖或 WebSocket 時,可使用 Gunicorn + UvicornWorker 的組合
  5. Let’s Encrypt + Certbot 提供免費 SSL 憑證——自動申請、安裝與續期,確保 HTTPS 安全連線
  6. Systemd 管理 Gunicorn 實現開機自動啟動與崩潰自動重啟——建立 socket 與 service 檔案即可完成設定
  7. 部署前檢查清單 確保所有安全與效能設定到位——使用 python manage.py check --deploy 自動檢查常見問題

下一篇我們將深入探討 Django 的 進階資料庫操作 ,學習連線池、Raw SQL 查詢與交易管理等進階技術。

BenZ Software Developer

熱愛技術的軟體開發者,在這裡分享程式開發經驗與學習筆記。