前言
發表 Docker 筆記以來,一直有網友提醒應改用 Kubernetes (K8S),關於這點在前篇文章已經提過,用 Docker / Docker-Compose 玩玩小網站還 OK,一旦涉及高可用性如備援、負載平衡,若不依賴現成管理架構,維運操作將複雜到會咬人。而 Kubernetes 正是目前容器管理框架的主流業界標準,尤其如打算將容器直接部署到雲端廠商(Azure、AWS、Google GCP),不會 Kubernetes 更是寸步難行。故在次聲明以正視聽,在企業環境如需考量高可用性、負載平衡或想直接部署到廠商雲端,一般不會用 Docker-Compose 而會採用 Kubernetes,請大家注意。
這篇筆記是我將部落格網站移入 Docker 容器的經驗分享,將記錄 Miniblog.Core ASP.NET Core 網站搬進 Docker 過程遇到的一些眉角。
Reverse Proxy 問題
由於我打算在同一機器上共享對外 IP 跑多個網站,因此採行前一篇筆記所說的「以 Compose 組合網站與 DB,網站對映 Host IP/Port,Nginx 另跑容器導向各網站 Port」策略。
目錄對應
部落格網站有一些執行期間更新的內容,包含 NLog Log 檔、文章圖檔、SQLite 資料庫等,這些內容不適合放在容器裡,故都需設 Volume 對映到 Host OS 的實際檔案,如此容器可任意刪除重建及升級,管理運用較方便。
時區問題
踩了雷才知道:Docker 容器內的時區跟 Host OS 是脫鉤的。即便本機已設好定為台北時區,Docker 容器預設為 UTC+0 時區,有兩種做法:
- 在 docker-compose.yml 中加註環境參數 TZ
- 新增 Volume 對映 /etc/localtime:/etc/localtime:ro,要求容器以 Host OS 的時區為準
第一種做法遇到以 Alpine Linux 版 Image 建的容器需要額外裝套件,故對映 /etc/localtime 較單純。
參考:設定 Docker Container 與 Host 相同時區的方法
取得真實來源 IP 問題
Reverse Proxy 來源 IP 在 ASP.NET Core + Nginx on CentOS 安裝筆記 提過,當 ASP.NET Core 架設在 Reverse Proxy 後方,直接看到的是 Reverse Proxy 的 IP,要得到真實來源 IP,在 Nginx config 需加註 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for,透過 HTTP Header 傳遞內容。而 ASP.NET Core 程式也需修改:
|
|
不過若 ASP.NET Core 運行於容器,綁定的 IP 不是 127.0.0.1 而是隔離網段 172.1x.0.x IP,此行為打破 UseForwardedHeaders 假設 Request 來自 localhost 的前題,就算設了 ForwardedHeaders, IHttpContextAccessor.HttpContext.Connection.RemoteIpAddress 讀到的仍是 172.1x.0.1 (隔離網段的 Gateway IP)。
由 ASP.NET Core 的原始碼,檢查規則為若 ForwardedHeadersOptions.KnownNetworks 或 ForwardedHeadersOptions.KnownProxies 有設定,來源 IP 必須要是 KnownNetworks 或 KnownProxies 才會認定請求為 Proxy 轉傳。而 KnownNetworks 及 KnownProxies 預設只有本機 IP。
|
|
解決方法有兩種,一種是將 172.x.0.0 加入 ForwardedHeadersOptions.KnownNetworks,但網段為 Docker 自由調配,最好寫成自動偵測不宜寫死。
另一個解法是將 KnownNetworks 與 KnownProxies 都清空,一般有來源 IP 被偽造的風險,但我們 ASP.NET Core 網站架構 Nginx Reverse Proxy 是唯一的入口,故我將其視為可接受做法:
|
|
參考:
Nginx 內容壓縮問題
跑了一陣子才發現,我用的 Nginx + Certbot 容器的 Nginx 設定檔 /etc/nginx/nginx.conf 預設未開啟 GZIP 壓縮。
我的解法是新增 Volume 對映將 /etc/nginx/nginx.conf 對應到 Host /etc/nginx/nginx.conf,並修改增加 gzip 那段內容:
|
|
Nginx 壓縮設定的意義可參考官方文件