先說一下需求情境,假設我用 HTTPS Nginx Docker 之懶人安裝法在 Linux 主機跑了一個 ASP.NET Core Docker / Python 網站 Docker,網站自動套用了 Let's Encrypt TLS 憑證且會自動更新。此時,你想要在這個現成的網站 Docker 下加掛子資料夾放 .html, .js 等靜態檔案,檔案直接放在 ~/htmls 目錄方便隨時修改。

第一種解法是如果 ASP.NET Core 有設 wwwroot、Python Flask 有用 app = Flask(__name__, static_folder='static') 對映靜態目錄,那麼在 docker-compose.yml 加一條 volumes 設定指向實體目錄就可以了。例如:

    volumes:                                                        
      - /home/jeffrey/htmls:/app/wwwroot/htmls                           

但如果 Docker 跑的網站本身沒有啟用靜態檔案對映,除了之前提過用 ASP.NET Core Minimal API、Python http.server 簡易架個靜態網站,還有個更快的做法 - 直接用 Nginx 內建的靜態網站功能。

第一次設定沒經驗,我花了半個小時才搞定,值得寫篇筆記備忘。

假設我的 index.html 檔放在 /home/jeffrey/htmls。第一步是在 ASP.NET Core/Python 的 Nginx 設定檔加一條 location /htmls 設定:

server {
    listen              443 ssl http2;
    server_name         <my-web-host>
    ssl_certificate     /etc/letsencrypt/live/<my-web-host>/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/<my-web-host>/privkey.pem;

    location /htmls {
        rewrite ^/htmls/(.*)$ /$1 break;
        root /var/www/htmls;
        index index.html;
    }

    location / {
        proxy_pass         http://localhost:5000;
        proxy_http_version 1.1;
        proxy_set_header   Upgrade $http_upgrade;
        proxy_set_header   Connection keep-alive;
        proxy_set_header   Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;
    }
}

設定包含三條內容:(註:此非最佳做法,見下方更新)

  1. rewrite ^/htmls/(.*)$ /$1 break; 改寫路徑,將流入請求路徑最前方的 /htmls 去除,否則使用者輸入 /htmls/blah.html 會對映成 /var/www/htmls/htmls/blah.html,多了一層。(最後的 break 指轉換完就確定,不再管其他 rewrite 指令)
  2. 將 /htmls 指向容器中的 /app/www/htmls 路徑
  3. 預設文件為 index.html

【2024-11-16 更新】感謝讀者 GO GO Chin 分享更簡便的解法:rewrite + root 可用一行 alias /var/www/htmls 取代。

二者比較:使用 root 時,URI 會被視為根目錄的一部分,即本例中的 /htmls;而 alias 則會拿掉 URI 中的 /htmls。故 alias 更適用如本案例非對映到根目錄的情境。

    location /htmls {
        alias /var/www/htmls;
        index index.html;
    }

如此,未來 Nginx 會將 http://<my-web-host>/htmls/example.html 指向 /app/www/htmls/example.html 傳回檔案內容。由於這項工作由 Nginx + Certbox Docker 負責,與 ASP.NET Core 或 Python 網站無關,故要修改的是 Nginx + Certbox 的 docker-compose.yml,將 /app/www/htmls 指向 /home/jeffrey/htmls:

services:
  nginx:
    image: docker.io/staticfloat/nginx-certbot
    container_name: nginx
    volumes:
      - /var/log/nginx:/var/log/nginx
      - /var/log/letsencrypt:/var/log/letsencrypt
      - /etc/nginx/nginx.conf:/etc/nginx/nginx.conf
      - /etc/nginx/conf.d:/etc/nginx/conf.d
      - /etc/letsencrypt:/etc/letsencrypt
      - /home/jeffrey/htmls:/var/www/htmls
    restart: always
    environment:
      - CERTBOT_EMAIL=<email>
    network_mode: "host"

接著 docker-compose down; docker-compose up -d 重啟 Nginx Docker,醬就大功告成囉~

This blog post demonstrates how to serve static files from a specific directory in an existing ASP.NET Core or Python web application using Nginx. The solution involves modifying the Nginx configuration to map a directory on the host machine to a directory within the Docker container, allowing for the direct serving of static files. This approach leverages Nginx’s built-in functionality, providing a quick and efficient way to handle static content.


Comments

Be the first to post a comment

Post a comment