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

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

内容简介:註:發表 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.


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

查看所有标签

猜你喜欢:

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

编程珠玑

编程珠玑

Jon Bentley / 人民邮电出版社 / 2006-11 / 28.0

《编程珠玑》第一版是我早期职业生涯中阅读过的对我影响较大的书籍之一,在书中首次接触到的很多观点都让我长期受益。作者在这一版本中做了重要更新,新增加的很多例子让我耳目一新。——Steve McConnell,《代码大全》作者  如果让程序员列举出他们喜欢的书籍,Jon Bentley的《编程珠玑》一定可以归于经典之列。如同精美的珍珠出自饱受沙砾折磨的牡蛎,程序员们的精彩设计也来源泉于曾经折磨他们的实......一起来看看 《编程珠玑》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器