傳統.NET 4.x應用容器化體驗(2)

上一篇我們基於Windwos Server 2019 with Container初步跑了一個ASP.NET WebForm應用程式。本篇我們來自己編譯部署一個ASP.NET MVC應用程式到Windows Container。

1 準備工作

這裡我們直接從github上clone微軟官方的dotnet-docker-samples項目,找到其中的aspnetmvc子項目。

github地址://github.com/Microsoft/dotnet-framework-docker

這是一個基於.NET 4.8的ASP.NET MVC應用程式,它運行起來和之前的ASP.NET WebForm的Sample一模一樣,這裡就不再演示。

clone下來後,在VS中編譯一下然後發布一下Release文件,最後將Release文件複製到阿里雲ECS的文件目錄下。

2 直接通過aspnet鏡像運行

首先,假設我們將其放到了C:\Releases\aspnetmvcapp目錄下:

這裡需要注意的是:和.NET Core不同,Dockerfile需要像上圖一樣放置在Release文件目錄之外。而在.NET Core下,Dockerfile可以放置在Release文件目錄下。

其次,我們看看這裡的Dockerfile是如何寫的。

# 運行環境
FROM mcr.microsoft.com/dotnet/framework/aspnet:4.8 AS runtime
# 工作目錄
WORKDIR /inetpub/wwwroot
# 拷貝文件
COPY Publish/. ./

很簡單,就三行搞定,拉取運行環境鏡像aspnet:4.8,設置工作目錄為/inetpub/wwwroot,最後將Publish文件目錄下的所有文件拷貝至容器的工作目錄之內,完事兒。然後,就是熟悉的build鏡像過程了,還是原來的味道:

> docker build -t reg.edisonzhou.cn/dotnet/samples:aspnetmvcapp .
Sending build context to Docker daemon  26.29MB
Step 1/3 : FROM mcr.microsoft.com/dotnet/framework/aspnet:4.8 AS runtime
 ---> 451a15b86af7
Step 2/3 : WORKDIR /inetpub/wwwroot
 ---> Running in fe87a7e897ca
Removing intermediate container fe87a7e897ca
 ---> 8737f6c38bfb
Step 3/3 : COPY Publish/. ./
 ---> 419e149fcfc9
Successfully built 419e149fcfc9
Successfully tagged reg.edisonzhou.cn/dotnet/samples:aspnetmvcapp

生成的鏡像到底有多大?8.48G!

> docker images
REPOSITORY                                   TAG            IMAGE ID       CREATED          SIZE
reg.edisonzhou.cn/dotnet/samples                    aspnetmvcapp   419e149fcfc9   12 seconds ago   8.48GB
mcr.microsoft.com/dotnet/framework/aspnet    4.8            451a15b86af7   4 weeks ago      8.45GB

可以看到,基礎運行鏡像aspnet:4.8就有8.45G,我們打包出來的只多了300M左右。

為啥aspnet:4.8這個鏡像這麼大?通過瀏覽docker hub對應鏡像的主頁,我們可以了解到,這個鏡像包括了以下幾個組成部分:

翻譯過來就是下面這幾個部分:

(1) 作業系統鏡像:Windows Server Core

(2) WebServer:IIS 10

(3) 基礎框架:.NET Framework

(4) 框架擴展:.NET Extension for IIS

其中,作業系統鏡像是最大的內容。關於這個鏡像的細節,可以瀏覽://hub.docker.com/_/microsoft-dotnet-framework-aspnet

最後,我們可以直接基於我們打包的鏡像來run一個容器實例了:

>docker run --name aspnet_mvc_sample --rm -it -d -p 8000:80 reg.edisonzhou.cn/dotnet/samples:aspnetmvcapp

通過查看容器日誌,我們可以了解到IIS已經成功啟動本站點:

> docker logs aspnet_mvc_sample

 Service 'w3svc' has been stopped

 Service 'w3svc' started

最終的效果,我們也可以通過 //localhost:8000 訪問到,和上一篇的效果一模一樣。

3 通過sdk編譯打包一體化

我們都知道,在Dockerfile中除了可以直接簡單地引入運行環境鏡像,也可以引入sdk鏡像來執行編譯和打包的操作,這一特點十分適合在持續集成的任務中執行。

因此,首先,我們將上面的Dockerfile改一下:

FROM mcr.microsoft.com/dotnet/framework/sdk:4.8 AS build
WORKDIR /app

# copy csproj and restore as distinct layers
COPY *.sln .
COPY aspnetmvcapp/*.csproj ./aspnetmvcapp/
COPY aspnetmvcapp/*.config ./aspnetmvcapp/
RUN nuget restore

# copy everything else and build app
COPY aspnetmvcapp/. ./aspnetmvcapp/
WORKDIR /app/aspnetmvcapp
RUN msbuild /p:Configuration=Release -r:False

FROM mcr.microsoft.com/dotnet/framework/aspnet:4.8 AS runtime
WORKDIR /inetpub/wwwroot
COPY --from=build /app/aspnetmvcapp/. ./

其次,我們將源程式碼拷貝到阿里雲ECS下,假設在C:\Sources\aspnetmvcapp目錄下。

然後,就又是熟悉的build鏡像過程了,還是原來的味道:

> docker build -t reg.edisonzhou.cn/dotnet/samples:aspnetmvcapp-v2 .

這裡編譯涉及到Nuget Restore的過程,可能會稍微慢一點。

有了打包好的鏡像,我們再來運行一下容器實例:

> docker stop aspnet_mvc_sample
> docker run --name aspnet_mvc_sample --rm -it -d -p 8000:80 reg.edisonzhou.cn/dotnet/samples:aspnetmvcapp-v2

最終的效果,我們還是可以通過 //localhost:8000 訪問到。

4 更多

Docker Compose

我們也可以在Windows Server上安裝Docker Compose來進行單主機的容器編排,在Linux上操作Docker Compose的經驗同樣也可以平滑遷移到Windows Container上:

>Invoke-WebRequest https://github.com/docker/compose/releases/download/1.25.4/docker-compose-Windows-x86_64.exe -UseBasicParsing -OutFile $env:ProgramFiles\docker\docker-compose.exe
>docker-compose version

資源限制

我們也可以為Windows Container設置資源限制,例如下面我們為ASP.NET MVC的這個sample設置只能使用1個cpu,最大記憶體限制1024M:

docker run --name aspnet_mvc_sample --rm -it -d -p 8000:80 --cpus 1 -m 1024m reg.edisonzhou.cn/dotnet/samples:aspnetmvcapp

掛載本地文件

我們也可以為Windows Container掛載本地文件目錄用於映射應用程式的文件,比如config文件等:

docker run --name aspnet_mvc_sample --rm -it -d -p 8000:80 --cpus 1 -m 1024m -v C:\IIS\config\aspnetmvcapp:C:\inetpub\wwwroot\Configs reg.edisonzhou.cn/dotnet/samples:aspnetmvcapp

5 總結

本文介紹了如何在Windows Container下通過Dockerfile實現.NET 4.x應用程式的編譯打包構建過程,並以一個ASP.NET MVC的Sample示例演示了整個過程。

下一篇,我們會實現將編譯的鏡像推送到harbor私有鏡像倉庫,並嘗試在Windows Server端拉取harbor中的鏡像並run一下。