ASP.NET Core Docker 筆記 1 - 初探

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

内容简介:前面研究過容器化及 Docker 這幾年熱到發燙,有些人甚至認為它已在軟體產業掀起一波革命。(我親身體驗的感想也是:Wow! 難怪會爆紅) 此刻才起步已算遲了,但也不是沒有好處 - 晚起鳥兒有更多蟲可以吃 XD,Docker 相關的文章資源多如牛毛,這裡便不多花篇幅贅述觀念與基本操作,只簡單整理我對 Docker 的理解:參考資料:

前面研究過 在 CentOS 安裝及設定 ASP.NET Core + Nginx ,習得徒手在 CentOS 安裝部署伺服器的技能,依循 Roadmap 來到下一階段 - 學習使用 Docker 簡化部署。

容器化及 Docker 這幾年熱到發燙,有些人甚至認為它已在軟體產業掀起一波革命。(我親身體驗的感想也是:Wow! 難怪會爆紅) 此刻才起步已算遲了,但也不是沒有好處 - 晚起鳥兒有更多蟲可以吃 XD,Docker 相關的文章資源多如牛毛,這裡便不多花篇幅贅述觀念與基本操作,只簡單整理我對 Docker 的理解:

  1. Container (容器)可以想成極度輕量化的虛擬機器(Virtual Machine),用法及優點與 VM 相同,能在一台 Host OS 同時運行多個彼此隔離的應用程式環境,但差別在 Container 會共用底層 Host OS,相較 VM 需各跑一份 Guest OS 能省下可觀的記憶體、磁碟,因此 Container 多了啟動速度快,耗用資源少(與直接跑應用程式相去不遠)的優勢。一台 4GB RAM 的機器頂多跑 2 - 3 台 VM 就緊繃了,但執行數十上百個 Container 不是問題。 2 Container 跟 VM 一樣具有很好的隔離效果,每個 Container 有自己的獨立作業環境(記憶體、磁碟空間、網路),不會彼此干擾,不必擔心 Container A 改系統設定害 Container B 跑不起來,或是兩個 Container 互相搶奪 80 Port,拿到 Image 就一定能在自己的機器跑起來。Container 在這方面的特性與 VM 完全相同,但因為不用包入作業系統,體積縮小許多,耗用記憶體也少,但便利性完全不減,取得 Container Image,靠一行指令幾秒內就能在機器把程式跑起來。
  2. Docker Hub 上有超過 10 萬個 Container Image,從 PHP 、Node,js、Apache、 MySQL 、Mongo DB、Nginx、 Redis 、ASP.NET Core... 幾乎想得到的都有,下指令自動下載 Image,幾秒鐘就裝好一台 DB、Web 伺服器,再下個指令又裝好第二台,不用擔心跟作業系統不相容、與其他軟體相衝、系統環境有誤導致安裝失敗,這就是 Docker 最迷人的所在。而我們也可將自己的專案網站做成 Image,交給測試人員測試,交付 OP 幾秒部署上線,也能將做好的 Image 上傳到 Docker Hub 與全世界分享。
  3. Docker Container 起初是基於 Linux Container 技術,故在 Container 只能跑 Linux 平台應用程式,雖然在 Windows 也有 Docker for Windows ,但背後是用 Hyper-V 跑 Linux 虛擬機執行 Docker Engine 再跑 Docker Container。後來微軟也依循相同概念發展出 Windows Container,並融入 Docker 體系,自此 Docker Container 開始有 Linux Container、Windows Container 之分,Windows Container 裡跑的就是不折不扣的 Windows 程式。參考: 安裝 Docker 容器環境 - Windows Server 2016
    從此, 在 Container 裡跑 ASP.NET WebForm 不再是夢。
  4. Windows Container 問市後,ASP.NET Core 程式容器化有 Linux Container 與 Windows Container 兩種選擇。基於 Linux Container 資源數量上的優勢,加上耗用資源較少,軟硬體成本低,我選擇 Linux Container。
  5. 雖然 Container 間共用底層作業系統,Docker Engine 為容器中的應用程式提供隔離不受干擾的空間(記憶體、檔案系統、網路 Port)。例如:容器 A 寫入 /etc/aaa/default.conf 不影響容器 B /etc/aaa/default.conf 的內容、容器 A 與容器 B 都繫結到 80 Port 也不會衝突。 先前文章 提過將 Kestrel 轉為 Linux 服務、設定 www-data 執行權限... 等步驟,改用 Docker 後簡單很多,生命週期由 Docker 控制,在容器內部權限一律為 root 不需額外規劃權限,直接跑 dotnet WebApp.dll 聽 5000 Port 就好。

參考資料:

Docker 安裝與基本操作的參考資料很多,這裡不多介紹,直接來幾個練習暖身:在 CentOS 上用 Docker 下載現成 Conatiner Image 執行 Nginx 伺服器,再用預設專案範本建立 ASP.NET Core 網站並包進 Container 執行。最後將二者串接在一起,使用 Nginx 做為 ASP.NET Core 網站的 Reverse Proxy。

  1. 執行 Nginx Container

    sudo docker run --name mynginx -d -p 80:80 --rm nginx

    不誇張,真的只要這行 Nginx 就好了。-d 把 Container 丟到背景執行不要佔用命令列視窗,-p 80:80 表示將 Container 的 80 Port 對應到 Host OS 的 80 Port,--rm 表示 Container 停止時自動刪除。開個 Chrome 連上 Host OS 的 80 Port,Nginx 已經準備就緒,skr~ ASP.NET Core Docker 筆記 1 - 初探 註:docker 指令需繫結 Unix Socket,必須以 SuperUser 權限執行,將使用者加入 Docker 群組可省去每次加 sudo 的麻煩。參考: Manage Docker as a non-root user

    sudo groupadd docker
    sudo usermod -aG docker $USER

    BUT,這招在 CentOS/Fedora/RHEL 不管用! ,但有替代方案:在 /etc/sudoers 加入 yourUserAccount ALL=(ALL) NOPASSWD: /usr/bin/docker 開放 sudo docker 時不用敲密碼,再用 alias docker="sudo /usr/bin/docker" 建立同義詞,也可做到不必 sudo 敲密碼跑 docker 指令。

  2. 將 ASP.NET Core 專案包進 Container 使用 .NET Core CLI 建立 MVC 專案,修改 Startup.cs 取消 app.UseHttpsRedirection(),以 Kestrel 執行 ASP.NET Core 網站。

    dotnet new mvc
    sed -i -e 's/app.UseHttps/\/\/app.UseHttps/' Startup.cs
    dotnet publish
    dotnet bin/Debug/netcoreapp2.1/web.dll

    由於 5000 Port 預設不對外開放,懶得開防火牆,在本機用 curl httq://localhost:5000 驗證網站運行中。

    ASP.NET Core Docker 筆記 1 - 初探

    驗證程式可執行後,寫個 Dockerfile 腳本將程式封裝成 Docker Image,這部分細節可參考保哥的文章: 如何將 ASP.NET Core 2.1 網站部署到 Docker 容器中

    在實務環境可以設計成全自動化測試流程,到版控抓原始碼放進內含 .NET Core SDK 的 Container 編譯,將結果包成只有 .NET Core Runtime 的 Container Image,用它建立 Container 進行 E2E 測試,一切自動化。這裡為求簡便,我選擇用只有 Runtime 的 Container Image 當成基底,將在 Host OS 編譯好的檔案複製到 Container /app 目錄,Dockerfile 內容如下:

    FROM microsoft/dotnet:2.1-aspnetcore-runtime
    WORKDIR /app
    COPY ./bin/Debug/netcoreapp2.1 ./
    ENTRYPOINT ["dotnet", "web.dll"]

    做好 Dockerfile 後執行 docker build,Docker 會從 Docker Hub 下載 microsoft/dotnet:2.1-aspnetcore-runtime (microsoft/dotnet 是 Image 名稱,同一 Image 常有多種版本可選擇,:2.1-aspnetcore-runtime 是標籤可用來指定版本),-t 參數指定 Image 名稱為 testapp。Container Image 做好,後接著用 docker run -d --rm --name myapp -p 5000:80 testapp 用剛做好的 Image 建立 Container,ASP.NET Core 專案在 Container 執行時,預設聽 80 Port,故我們用 -p 5000:80 將 Container 的 80 Port 導向 Host OS 的 5000 Port。用 curl 驗證網站運行中。

    ASP.NET Core Docker 筆記 1 - 初探

    使用 docker images 及 docker ps 我們可以看到剛才建立的 Image testapp 及 Container myapp:

    ASP.NET Core Docker 筆記 1 - 初探
  3. 至此,我們做了兩個 Container,myginx 聽 Host OS 80 Port,myapp 聽 Host OS 的 5000 Port,一步要將 Nginx 設成 ASP.NET Core 網站的 Reverse Proxy。

    做法跟先前文章介紹過的概念差不多,為求簡便我們直接修改 conf.d/default.conf 將進入 80 Port 的請求導向 5000 Port。(正規做法建議一個網站開一個 conf 檔) Container 的檔案系統是隔離的,將設定檔保存在 Container 裡不是好主意 - 除非每次修改設定存檔就重新產生 Image 並要求未來一律改用新版 Image 建立 Container,否則一旦 Conatiner 被刪除,設定就會消失。同樣問題也會發生在資料庫檔、Log 檔等執行期間要動態更新的內容,這類檔案保存在 Host OS 檔案系統上比較合理,程式換版換了 Container Image 資料才不受影響。Docker 靠 Volume 解決資料保存及共用需求,docker run 有個 -v host-path:container-path 可將 Host OS 特定目錄或檔案對映到 Container,讓 Container 能讀寫 Host OS 的檔案。

    對 Nginx Container 來說,Reverse Proxy 設定放在 /etc/nginx/conf.d,我選擇在 Host OS 也建立相同路徑並將 Container 的 default.conf 複製出來(指令如下),修改後在 docker run 加上 -v /etc/nginx/conf.d:/etc/nginx/conf.d 對映回去:

    sudo docker cp mynginx:/etc/nginx/conf.d /etc/nginx/conf.d
    ASP.NET Core Docker 筆記 1 - 初探

    修改 /etc/nginx/conf.d/default.conf,目前是將進入 Nginx 80 Port 的請求導向 Host OS 5000 Port,但從 Docker Container 存取 Host OS IP 有些眉角,Mac 或 Windows Docker 18.3+ 可用 DNS 名稱 host.docker.internal 指向 Host OS IP,但 Docker for Linux 18.4+ 這招己失效。 參考

    省事做法是 docker run 時用 --network host 讓 Container 直接繫結本機 IP 而非 Docker 所屬的隔離網段,如此 default.conf 的 proxy_pass 指向 localhost:5000 即可。

    server {
         listen       80;
         server_name  localhost;
    
         #charset koi8-r;
         #access_log  /var/log/nginx/host.access.log  main;
    
         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;
         }
     }

    完整啟動指令如下:

    sudo docker run --name mynginx -d -v /etc/nginx/conf.d:/etc/nginx/conf.d --network host nginx

    從遠端開啟 Chrome 連上 Host OS 的 80 Port,我們已被順利導向 ASP.NET Core 網站,顯示設定成功。

    ASP.NET Core Docker 筆記 1 - 初探

經過以上練習,我們體驗了從 Docker Hub 下載 Image 建立 Docker Containter 跑 Nginx、用 Dockerfile 將 ASP.NET Core 網站包成 Container、用 Port 映對 Host OS TCP Port 到 Container、使用 -v(--volume) 映對資料夾讓 Container 讀寫 Host OS 檔案。

而在實務應用上,相關的 Conatiner 需要組合在一起執行,例如一個 Container 跑網站,一個 Container 跑資料庫,此時可用 docker-compose 簡化管理;另外 Docker 也提供 Bridge 為相關 Container 建立專屬的隔離網段,防止外界接觸到不想對外公開的網路服務,也避免不相干的 Container 彼此干擾... 這些議題就留待下一篇文章討論。

Explaining the idea of using Docker containers to simplify ASP.NET Core web. In the article, I setup two independent Docker containers to run ASP.NET Core with Nginx reverse proxy.


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

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

从零到百亿

从零到百亿

〔美〕卡罗·白朗、Karel Baloun、卡罗·白朗 / 译言网 / 中国书籍出版社 / 2007 / 15.00元

Facebook是一个发源于哈佛大学、为全美大学生服务的社交网站。按照流量,这个网站在世界范围排名第8名;按照价值,业界对Facebook公司的估值超过10亿美元。Facebook创建于2004年2月,这样的高速增长成为当今互联网发展的一个奇迹。 《Inside Facebook》这本书是原作者卡罗·白朗(Karel Baloun)作为Facebook的第一位高级软件开发人员之一,在Face......一起来看看 《从零到百亿》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

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

Base64 编码/解码