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 伺服器,基於 uvloop 與 httptools 構建,效能表現優異。

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

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

本週主打

AI 自動化入門包

你每天手動在做的那些煩事,其實 AI 可以自己跑。這份給你 10 個照著做就會的自動化工作流 + 50 個複製即用的提示詞,不用會寫程式。

看看這個產品 →