ASP.NET Core Docker 筆記 4 - ASP.NET Core 網站容器化經驗分享

栏目: ASP.NET · 发布时间: 6年前

内容简介:註:發表 Docker 筆記以來,一直有網友提醒應改用 Kubernetes (K8S),關於這點在前篇文章已經提過,用 Docker / Docker-Compose 玩玩小網站還 OK,一旦涉及高可用性如備援、負載平衡,若不依賴現成管理架構,維運操作將複雜到會咬人。而 Kubernetes 正是目前容器管理框架的主流業界標準,尤其如打算將容器直接部署到雲端廠商(Azure、AWS、Google GCP),不會 Kubernetes 更是寸步難行。故在次聲明以正視聽,在企業環境如需考量高可用性、負載平衡

註:發表 Docker 筆記以來,一直有網友提醒應改用 Kubernetes (K8S),關於這點在前篇文章已經提過,用 Docker / Docker-Compose 玩玩小網站還 OK,一旦涉及高可用性如備援、負載平衡,若不依賴現成管理架構,維運操作將複雜到會咬人。而 Kubernetes 正是目前容器管理框架的主流業界標準,尤其如打算將容器直接部署到雲端廠商(Azure、AWS、Google GCP),不會 Kubernetes 更是寸步難行。故在次聲明以正視聽,在企業環境如需考量高可用性、負載平衡或想直接部署到廠商雲端,一般不會用 Docker-Compose 而會採用 Kubernetes,請大家注意。

這篇筆記是我將部落格網站移入 Docker 容器的經驗分享,將記錄 Miniblog.Core ASP.NET Core 網站搬進 Docker 過程遇到的一些眉角。

  1. Reverse Proxy 問題

    由於我打算在同一機器上共享對外 IP 跑多個網站,因此採行前一篇筆記所說的「以 Compose 組合網站與 DB,網站對映 Host IP/Port,Nginx 另跑容器導向各網站 Port」策略。

  2. 目錄對應

    部落格網站有一些執行期間更新的內容,包含 NLog Log 檔、文章圖檔、SQLite 資料庫等,這些內容不適合放在容器裡,故都需設 Volume 對映到 Host OS 的實際檔案,如此容器可任意刪除重建及升級,管理運用較方便。

  3. 時區問題

    踩了雷才知道:Docker 容器內的時區跟 Host OS 是脫鉤的。即便本機已設好定為台北時區,Docker 容器預設為 UTC+0 時區,有兩種做法:

    1. 在 docker-compose.yml 中加註環境參數 TZ
    2. 新增 Volume 對映 /etc/localtime:/etc/localtime:ro,要求容器以 Host OS 的時區為準
      第一種做法遇到以 Alpine Linux 版 Image 建的容器需要額外裝套件,故對映 /etc/localtime 較單純。
      參考: 設定 Docker Container 與 Host 相同時區的方法
  4. 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 程式也需修改:

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
     {
         app.UseForwardedHeaders(new ForwardedHeadersOptions
         {
             ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
         });

    不過若 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。

    /// <summary>
         /// Addresses of known proxies to accept forwarded headers from.
         /// </summary>
         public IList<IPAddress> KnownProxies { get; } = new List<IPAddress>() { IPAddress.IPv6Loopback };
    
         /// <summary>
         /// Address ranges of known proxies to accept forwarded headers from.
         /// </summary>
         public IList<IPNetwork> KnownNetworks { get; } = new List<IPNetwork>() { new IPNetwork(IPAddress.Loopback, 8) };

    解決方法有兩種,一種是將 172.x.0.0 加入 ForwardedHeadersOptions.KnownNetworks,但網段為 Docker 自由調配,最好寫成自動偵測不宜寫死。另一個解法是將 KnownNetworks 與 KnownProxies 都清空,一般有來源 IP 被偽造的風險,但我們 ASP.NET Core 網站架構 Nginx Reverse Proxy 是唯一的入口,故我將其視為可接受做法:

    var forwardingOptions = new ForwardedHeadersOptions()
     {
         ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
     };
     forwardingOptions.KnownNetworks.Clear(); //its loopback by default
     forwardingOptions.KnownProxies.Clear();
     app.UseForwardedHeaders(forwardingOptions);

    參考:

  5. Nginx 內容壓縮

    跑了一陣子才發現,我用的 Nginx + Certbot 容器的 Nginx 設定檔 /etc/nginx/nginx.conf 預設未開啟 GZIP 壓縮。我的解法是新增 Volume 對映將 /etc/nginx/nginx.conf 對應到 Host /etc/nginx/nginx.conf,並修改增加 gzip 那段內容:

    user  nginx;
     worker_processes  1;
    
     error_log  /var/log/nginx/error.log warn;
     pid        /var/run/nginx.pid;
    
     events {
         worker_connections  1024;
     }
    
    
     http {
         include       /etc/nginx/mime.types;
         default_type  application/octet-stream;
    
         log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                           '$status $body_bytes_sent "$http_referer" '
                           '"$http_user_agent" "$http_x_forwarded_for"';
    
         access_log  /var/log/nginx/access.log  main;
    
         sendfile        on;
         #tcp_nopush     on;
    
         keepalive_timeout  65;
    
         gzip  on;
         gzip_min_length 1000;
         gzip_buffers 4 16k;
         gzip_comp_level 5;
         gzip_types text/plain application/x-javascript text/css application/xml text/javascript;
    
         include /etc/nginx/conf.d/*.conf;
     }

    Nginx 壓縮設定的意義可參考 官方文件

Sharing experience of moving a ASP.NET Core web site into Docker container, including to set volume mappings, set timezone and modify code to get actual client IP behinde reverse proxy.


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

今日简史

今日简史

[以] 尤瓦尔·赫拉利 / 林俊宏 / 中信出版集团 / 2018-8 / 68

四年前,尤瓦尔•赫拉利的《人类简史》横空出世,颠覆了我们关于人类进化的认知。2016年,他的《未来简史》再度惊艳四座,刷新了我们对未来的想象,掀起了全球关于人工智能讨论的新思潮。现在,“简史三部曲”收官之作《今日简史》推出,将目光聚焦到当下,直面今天关乎我们每个人命运的问题和挑战。 尤瓦尔•赫拉利认为,智人之所以能够崛起成为地球的主宰者,主要原因在于其具备了虚构故事的能力。然而,在当前这样一......一起来看看 《今日简史》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

SHA 加密
SHA 加密

SHA 加密工具