全部產品
Search
文件中心

Elastic Compute Service:使用Nginx+uWSGI部署Django專案

更新時間:Sep 20, 2025

在ECS執行個體上部署Django專案,可通過Nginx分發靜態檔案,結合uWSGI管理應用進程,從而實現動靜分離,提升服務效能。

工作原理

  1. 瀏覽器向伺服器發送HTTP或HTTPS請求。

  2. Nginx作為前端伺服器,接收傳入的請求。

    • 靜態資源(如CSS、JavaScript、圖片)的請求,Nginx直接從本地提供檔案。可提升響應速度,並減輕Django應用的負載。

    • 動態請求則轉寄至uWSGI伺服器。

  3. uWSGI接收到Nginx轉寄的請求,將其傳遞給Django應用進行處理,實現負載平衡。

  4. Django應用處理請求,執行商務邏輯(如資料庫查詢、模板渲染),返迴響應資料。

操作步驟

步驟一:準備資源

  1. 建立專用網路與交換器

  2. 建立ECS執行個體。

    1. 前往執行個體購買頁。選擇自訂購買頁簽。

    2. 執行個體規格:推薦使用至少2 vCPU和4 GiB記憶體。

    3. 鏡像:Alibaba Cloud Linux 3。

    4. 網路和安全性群組:

      • 網路:選擇已建立的Virtual Private Cloud

      • 公網IP:勾選分配公網 IPv4 地址

      • 安全性群組:選擇建立安全性群組並勾選HTTP (TCP:80)

  3. 配置運行時環境。

    1. 使用Workbench登入Linux執行個體

    2. 安裝Nginx與Python開發套件(編譯uWSGI)。

      預設源的Nginx版本過舊,有安全風險。添加Nginx官方源以安裝最新的穩定版本。
      #添加Nginx官方源到系統中
      sudo tee /etc/yum.repos.d/nginx.repo <<-'EOF'
      [nginx-stable]
      name=nginx stable repo
      baseurl=http://nginx.org/packages/centos/8/$basearch/
      gpgcheck=1
      enabled=1
      gpgkey=https://nginx.org/keys/nginx_signing.key
      module_hotfixes=true
      EOF
      sudo yum install -y python3.8 python38-devel pcre-devel gcc make nginx
      #安裝Django和uWSGI
      sudo python3.8 -m pip install --upgrade pip wheel -i https://mirrors.aliyun.com/pypi/simple
      sudo python3.8 -m pip install "Django>=4.2,<5.0" "uwsgi>=2.0.23" -i https://mirrors.aliyun.com/pypi/simple
    3. 建立logs,static,media目錄分別用於儲存日誌,靜態檔案和媒體檔案,建立/run/uwsgi目錄用於存放socket檔案。

      sudo mkdir -p /srv/django-app/{logs,static,media}
      sudo mkdir -p /run/uwsgi

步驟二:部署Django應用

  1. 建立一個Django樣本專案。

    推薦為專案建立Python虛擬環境,可以隔離專案依賴,避免不同專案間的包版本衝突。
    sudo /usr/local/bin/django-admin startproject myproject /srv/django-app/
  2. 修改專案設定檔/srv/django-app/myproject/settings.py,以滿足生產環境的安全和效能要求。

    • 設定DEBUG屬性為False。此操作可防止應用出錯時泄露敏感配置與代碼細節。

    • 設定ALLOWED_HOSTS屬性為執行個體的公網IP地址。如果此列表為空白,應用將無法啟動。這是Django的一項內建安全機制。

      IP地址須作為字串包含在列表中,例如['xxx.xxx.xxx.xxx']
    • 在檔案末尾添加STATIC_ROOT = BASE_DIR / 'static',用於指定靜態檔案目錄。

  3. 同步樣本專案的靜態檔案至指定目錄(STATIC_ROOT),以供Nginx直接存取。

    sudo python3.8 /srv/django-app/manage.py collectstatic --noinput
  4. 執行資料庫遷移,在資料庫中建立儲存使用者等應用資料所需的表結構。

    Django專案預設使用SQLite3資料庫,該配置不適用於生產環境。修改myproject/settings.py檔案中的DATABASES設定,可將其替換為其他資料庫。
    sudo python3.8 /srv/django-app/manage.py migrate
  5. 建立專案的管理員賬戶,用於後續登入Django管理後台。

    sudo python3.8 /srv/django-app/manage.py createsuperuser

步驟三:配置uWSGI服務

  1. 建立uWSGI設定檔/etc/django-app.ini。指定專案路徑、進程模型、socket檔案位置和記錄檔。

    processes參數可根據執行個體CPU核心數進行調整,建議設定為核心數 * 2
    建議使用非特權使用者運行服務,即使應用被攻破,攻擊者也無法獲得伺服器的最高許可權。
    [uwsgi]
    # 專案配置
    chdir = /srv/django-app
    module = myproject.wsgi:application
    
    # 進程配置
    master = true
    processes = 4
    threads = 2
    
    # 網路與許可權配置
    socket = /run/uwsgi/django-app.sock
    chmod-socket = 666
    chown-socket = root:root
    vacuum = true
    
    # 安全與回合組態
    uid = root
    gid = root
    die-on-term = true
    
    # 日誌配置
    logto = /srv/django-app/logs/uwsgi.log
  2. 在後台啟動 uWSGI 服務,使其在終端關閉後也能持續運行。

    可使用ps aux | grep uwsgi命令檢查uWSGI進程狀態。
    nohup /usr/local/bin/uwsgi --ini /etc/django-app.ini &
  3. (可選)使用systemd管理uWSGI服務,可以實現開機自啟和更可靠的服務管理。

    1. 建立啟動設定檔/etc/systemd/system/uwsgi-django-app.service

      [Unit]
      Description=uWSGI service for Django App
      After=network.target
      
      [Service]
      User=root
      Group=root
      RuntimeDirectory=uwsgi
      ExecStart=/usr/local/bin/uwsgi --ini /etc/django-app.ini
      Restart=always
      KillSignal=SIGQUIT
      Type=notify
      NotifyAccess=all
      
      [Install]
      WantedBy=multi-user.target
    2. 啟動uWSGI服務並設定開機自啟。

      sudo systemctl daemon-reload
      sudo systemctl start uwsgi-django-app
      sudo systemctl enable uwsgi-django-app

      檢查服務狀態。

      sudo systemctl status uwsgi-django-app

步驟四:配置Nginx作為前端伺服器

  1. 將下方配置中的<server_ip>替換為執行個體公網IP,並將內容儲存為Nginx設定檔/etc/nginx/conf.d/django-app.conf

    # 定義一個 upstream,指向 uWSGI 的 socket 檔案
    upstream django_backend {
        server unix:/run/uwsgi/django-app.sock;
    }
    
    server {
        listen 80;
        server_name <server_ip>; # 替換為公網IP
        charset utf-8;
        client_max_body_size 20M;
    
        # 靜態檔案服務
        location /static/ {
            alias /srv/django-app/static/;
        }
    
        # 媒體檔案服務
        location /media/ {
            alias /srv/django-app/media/;
        }
    
        # 代理所有其他請求到 Django 應用
        location / {
            include /etc/nginx/uwsgi_params;
            uwsgi_pass django_backend;
        }
    }
  2. 運行nginx -t命令驗證Nginx設定檔文法是否正確。

    若輸出包含syntax is oktest is successful,則表示配置正確。

  3. 重啟Nginx應用新配置並設定開機自啟。

    sudo systemctl restart nginx
    sudo systemctl enable nginx
  4. 訪問樣本專案登入頁面:http://<ECS的公網IP地址>/admin

生產應用建議

  • 使用非特權使用者運行服務:建立一個無登入許可權的系統使用者來運行應用,可以有效隔離許可權,提升伺服器安全性。即使應用代碼存在漏洞被利用,攻擊者也無法獲得伺服器的root許可權。

    #建立一個無登入許可權的系統使用者 (django-app)
    sudo useradd --system --shell /bin/false --home /srv/django-app django-app
    #應用目錄的所有權更改為django-app使用者。
    sudo chown -R django-app:django-app /srv/django-app
  • 使用 Python 虛擬環境:為每個專案建立獨立的Python虛擬環境,可以隔離專案依賴,避免不同專案間的包版本衝突。這使得部署環境更加純淨、可預測,並且易於複現。

    # 建立虛擬環境
    python3.8 -m venv venv
    # 啟用虛擬環境
    source venv/bin/activate

常見問題

訪問頁面顯示502 Bad Gateway

此錯誤通常表示Nginx無法與uWSGI正常通訊。

  • 檢查uWSGI服務狀態:systemctl status uwsgi-django-app

  • 查看uWSGI日誌:tail -f /srv/django-app/logs/uwsgi.log

  • 檢查socket檔案是否存在及其許可權:ls -l /run/uwsgi/django-app.sock

訪問靜態檔案顯示403 Forbidden

此問題是由於 Nginx 進程沒有足夠的許可權讀取靜態檔案目錄。

  • 確認Nginx的運行使用者(在Alibaba Cloud Linux上通常是nginx)對/srv/django-app/static/目錄及其所有子檔案和子目錄具有讀取(r)和執行(x)許可權。

訪問頁面顯示500 Internal Server Error

此錯誤表示 Django 應用在處理請求時內部發生錯誤。

  1. 開啟偵錯模式定位問題:臨時將專案設定檔settings.py中的DEBUG設定為True,然後重啟uWSGI服務並重新整理頁面。瀏覽器將顯示詳細的錯誤堆棧資訊,有助於快速定位問題。

    重要

    此操作僅限調試使用,問題解決後須將DEBUG改回False,以防敏感資訊泄露。

  2. 檢查uWSGI日誌:錯誤資訊同樣會被記錄在uWSGI的記錄檔中,通過查看日誌可以擷取Django拋出的具體錯誤。