Apache2 + uWSGI + Flask → Nginx+ Gunicorn + Flask

前情提要

[筆記] Apache2 + Uncomplicated Firewall + uWSGI + Flask

停用 Apache2 和 uWSGI

中斷並停用 Apache2

  1. sudo systemctl stop apache2
  2. sudo systemctl disable apache2

中斷並停用uWSGI

  1. sudo uwsgi --stop {FlaskApps}/uwsgi/uwsgi.pid
  2. sudo nano /etc/rc.local
  3. 註解掉 (#) 開機自動啟動 uWSGI:# uwsgi --ini {FlaskApps}/uwsgi/uwsgi.ini

Gunicorn

  1. 安裝:
    sudo python3 -m pip install --upgrade pip
    sudo pip install gunicorn
  2. 創建 socket 資料夾:
    1. 宣告 shell variable (僅限當前執行的 shell 進程):FLASKAPPS="{FlaskApps}"
    2. sudo mkdir -p $FLASKAPPS/gunicorn_socket/
  3. 修正 socket 資料夾權限:
    1. sudo chown {Username}:www-data $FLASKAPPS/gunicorn_socket/
    2. sudo chmod g+w $FLASKAPPS/gunicorn_socket/
  4. 確認 Gunicorn 是否可運行
    1. sudo gunicorn --chdir $FLASKAPPS main:app\
      --workers 4 \
      --bind unix:$FLASKAPPS/gunicorn_socket/gunicorn.sock \
      --user {Username} --group www-data \
      --daemon

      ⇒ 會在 {FlaskApps}/gunicorn_socket 下生成 gunicorn.sock
    2. ps aux | grep gunicorn
      ⇒ 會看到數個 Gunicorn process (1 個 master process + 4 個 worker process)
    3. 模擬 HTTP請求
      curl --unix-socket $FLASKAPPS/gunicorn_socket/gunicorn.sock http://localhost/
  5. 設置開機自動啟動 Gunicorn
    1. 中止上一步中啟動的 Gunicorn processes
      sudo pkill gunicorn
    2. 創建 systemd service unit:
      1. sudo nano /etc/systemd/system/gunicorn_flask.service
      2. 將以下內容寫入 gunicorn_flask.service:
        [Unit]
        Description=Gunicorn instance to serve your Flask application
        # 確保網路服務啟動後才啟動 Gunicorn
        After=network.target
        
        [Service]
        # Gunicorn 執行的用戶和群組
        User={Username}
        Group=www-data
        # Gunicorn 尋找 main.py 的工作目錄
        WorkingDirectory={FlaskApps}
        
        # 啟動前,先清除舊的 Socket 檔案,避免權限或檔案鎖定衝突
        ExecStartPre=/bin/rm -f {FlaskApps}/gunicorn_socket/gunicorn.sock
        
        # Gunicorn 的完整啟動命令
        ExecStart=/usr/bin/env /usr/local/bin/gunicorn --chdir {FlaskApps} main:app --workers 4 --bind unix:{FlaskApps}/gunicorn_socket/gunicorn.sock
        
        # 重新啟動策略:如果服務失敗,立即重啟
        Restart=always
        KillSignal=SIGQUIT
        # 標準日誌輸出到 systemd 日誌中
        StandardOutput=syslog
        StandardError=syslog
        
        [Install]
        # 告訴 systemd 在進入多用戶模式(開機完成)時啟動此服務
        WantedBy=multi-user.target
    3. 設置開機自動啟動並開始執行 gunicorn_flask.service
      1. 重新載入 systemd:sudo systemctl daemon-reload
      2. 啟用 (設置開機自動啟動):sudo systemctl enable gunicorn_flask.service
      3. 立即啟動:sudo systemctl start gunicorn_flask.service
      4. 檢查服務狀態是否正常運作:sudo systemctl status gunicorn_flask.service
      5. (重啟服務:sudo systemctl restart gunicorn_flask.service)

Nginx

  1. 安裝:
    sudo apt update
    sudo apt install nginx
  2. 安裝完成後,Nginx 服務通常會自動啟動。
    檢查運行狀態:sudo systemctl status nginx
  3. 創建 Nginx 配置文件:
    1. sudo nano /etc/nginx/sites-available/default
      寫入以下內容:

      server {
          listen 80 default_server;
          listen [::]:80 default_server;
          server_name {Domain Name 1} [{Domain Name 2} ...];
      
          # 所有的 HTTP 流量將被重定向到 HTTPS
          return 301 https://$host$request_uri;
      }
    2. 測試 Nginx 配置語法:sudo nginx -t
    3. 重新載入 Nginx 服務 已啟用新配置:sudo systemctl reload nginx
  4. 設定 Uncomplicated Firewall 防火牆白名單:sudo ufw allow 'Nginx Full'
  5. Certbot
    1. 安裝:sudo apt install certbot python3-certbot-nginx -y
    2. ps aux | grep certbot找出
      是否有COMMAND使用了/usr/bin/certbot的 process?
      若有:sudo kill {PID}
    3. (確認先前是否有申請過 SSL 憑證:sudo certbot certificates
      若有:sudo certbot delete --cert-name {Certificate Name})
    4. sudo certbot --nginx -d {Domain Name 1} [-d {Domain Name 2} ...]
  6. 覆寫 Nginx 配置文件:
    1. sudo nano /etc/nginx/sites-available/default
      寫入以下內容:

      server {
          listen 80 default_server;
          listen [::]:80 default_server;
          server_name {Domain Name 1} [{Domain Name 2} ...];
      
          # 所有的 HTTP 流量將被重定向到 HTTPS
          return 301 https://$host$request_uri;
      }
      
      server {
      # 監聽 443 埠並啟用 SSL
          listen 443 ssl http2;
          listen [::]:443 ssl http2;
          server_name {Domain Name 1} [{Domain Name 2} ...];
      
          # 憑證路徑 (使用 Certbot 已經創建的憑證)
          ssl_certificate /etc/letsencrypt/live/{Certificate Name}/fullchain.pem; # managed by Certbot
          ssl_certificate_key /etc/letsencrypt/live/{Certificate Name}/privkey.pem; # managed by Certbot
          include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
          ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
      
          # 處理靜態檔案
          # location /static/ {
          #     alias {FlaskApps}/static/;
          # }
      
          # 代理給 Gunicorn
          location / {
              proxy_pass http://unix:{FlaskApps}/gunicorn_socket/gunicorn.s>
      
              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 https; # 告訴 Gunicorn 這是 HTTPS 請求
          }
      }
      
    2. 測試 Nginx 配置語法:sudo nginx -t
    3. 重新載入 Nginx 服務 已啟用新配置:sudo systemctl reload nginx

 

Last Updated on 2025/12/08 by A1go

目錄
Bitnami