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

我們都知道.NET Core應用可以跑在Docker上,那.NET Framework 4.x應用呢?藉助阿里雲ECS主機(Windows Server 2019 with Container版本),一切變得So Easy!

1 關於Windows Container

自從Windows Server 2016版開始,原生Docker就得到了支持,在這之前,想要在Windows系統上運行Docker(包括Windows 10),都得先裝一個Hyber-V的虛擬機,然後在虛擬機上跑Docker,完全無法發揮Docker在進程隔離級別的優勢。

下圖展示了兩種模式的區別:

可以確定的是,無論是哪種運行模式,我們都可以使用標準的Docker命令行進行操作,同時容器鏡像的格式也和Linux容器鏡像保持一致。

畫外音:這就意味着Windows Container可以通過docker hub或私有鏡像倉庫如Harbor進行分發,我們之前在Linux容器上的經驗積累也可以平滑遷移到Windows容器上。

但是,Windows Container受限於Windows內核屬性,只能跑Windows應用程序,比如和Windows內核強耦合的.NET Framework應用程序。這一點,也是攜程等.NET應用大戶選擇Windows Container的原因。而攜程曾經的問題,也正是目前我司所遇到的痛點,即在.NET與Java雙技術棧並存的前提下,如何統一運行環境和打包部署機制,成為了一大難題。在.NET 4.x(廣大核心業務系統)、.NET 5(部分新興服務) 與 Java (電商業務)應用共存的異構技術棧背景下,.NET 4.x又無法同時快速升級到.NET 5的歷史包袱前提下,統一運行環境 和 編排流程 對於整個技術團隊來說是很有必要的,而容器化帶來的紅利也應該要讓.NET Framework 4.x 應用程序享受到

2 關於阿里雲ECS與ACK

在現今企業服務器OS市場,Windows依然佔據半壁江山,其市場份額達60%之多,把Windows應用搬站上雲不僅僅是基礎設施的遷移,更重要的是通過Kubernetes等雲原生技術讓傳統的Windows應用架構體系升級,充分利用雲上的彈性、敏捷等能力,實現業務應用的快速迭代和交付。

阿里雲ECS主機率先提供了 Windows Server 2019 with Container 與 Windows Server Version 1909 with Container 兩個OS鏡像,滿足了.NET應用程序跑在Windows Container上的需求。Windows Version 1909鏡像是指運行在服務器核心模式下不含UI版本的系統,Version 1909不含UI沒有圖形界面,佔用服務器資源少。而Windows Server 2019 with Container鏡像版本,是指Windows鏡像是在原有的鏡像基礎上增加了Docker容器運行環境,如果在使用過程中需要Docker容器運行環境則可以選擇with Container版本鏡像。

更令人興奮的是,阿里雲容器服務已正式發佈Windows Container支持,用戶可通過控制台或Open API創建Windows Kubernetes集群並部署Windows容器。

阿里雲容器服務ACK通過Windows容器的支持,幫助企業輕鬆實現Windows容器應用的部署,其兼容kubernetes標準,支持cpu/memory資源編排,支持deployment/statefulset/job/cronjob等應用部署模型。同時用戶可以添加Linux節點,實現Linux/Windows應用混合部署的統一管理

想要進行Windows Server Node + Linux Node混合管理的童鞋,可以考慮一下阿里雲ACK服務。

3 快速開始

本篇會主要介紹在藉助阿里雲ECS(Windows Server 2019 with Container鏡像版本)來實現.NET 4.8應用的容器化初步運行。

第一步,選擇阿里雲ECS主機,在OS鏡像區域選擇Windows Server 2019 with Container鏡像。

第二步,遠程登錄阿里雲ECS主機,查看docker版本與信息。由於該鏡像版本已經設置好了Docker運行環境,因此無需再手動安裝(如果是Windows Server 2019鏡像版本的話則需要手動安裝)。

> docker version
Client: Mirantis Container Runtime
 Version:           20.10.5
 API version:       1.41
 Go version:        go1.13.15
 Git commit:        105e9a6
 Built:             05/17/2021 16:36:02
 OS/Arch:           windows/amd64
 Context:           default
 Experimental:      true

Server: Mirantis Container Runtime
 Engine:
  Version:          20.10.5
  API version:      1.41 (minimum version 1.24)
  Go version:       go1.13.15
  Git commit:       1a7d997053
  Built:            05/17/2021 16:34:40
  OS/Arch:          windows/amd64
  Experimental:     false

此外,阿里雲已經提前設置好了鏡像加速,因此也無需手動配置daemon.json設置鏡像加速源。

> docker info
Client:
 Context:    default
 Debug Mode: false
 Plugins:
  app: Docker Application (Docker Inc., v0.8.0)
  cluster: Manage Mirantis Container Cloud clusters (Mirantis Inc., v1.9.0)
  registry: Manage Docker registries (Docker Inc., 0.1.0)

Server:
 Containers: 1
  Running: 1
  Paused: 0
  Stopped: 0
 Images: 4
 Server Version: 20.10.5
 Storage Driver: windowsfilter
  Windows:
 Logging Driver: json-file
 Plugins:
  Volume: local
  Network: ics internal l2bridge l2tunnel nat null overlay private transparent
  Log: awslogs etwlogs fluentd gcplogs gelf json-file local logentries splunk syslog
 Swarm: inactive
 Default Isolation: process
 Kernel Version: 10.0 17763 (17763.1.amd64fre.rs5_release.180914-1434)
 Operating System: Windows Server 2019 Datacenter Version 1809 (OS Build 17763.1999)
 OSType: windows
 Architecture: x86_64
 CPUs: 1
 Total Memory: 1.92GiB
 Name: yz-jc-poc-ecs
 ID: P7LP:34B5:PQHH:YVKG:ADDM:5KOQ:6ATZ:CWNW:M74Z:D7SM:WAZO:R66T
 Docker Root Dir: C:\ProgramData\docker
 Debug Mode: false
 Registry: https://index.docker.io/v1/
 Labels:
 Experimental: false
 Insecure Registries:
  127.0.0.0/8
 Live Restore Enabled: false

第三步,Run一個.net framework控制台示例容器:

docker run --rm mcr.microsoft.com/dotnet/framework/samples:dotnetapp

運行結果如下圖所示:

我們也可以看到這個示例鏡像的大小,WTF,真的不小!

> docker images
REPOSITORY                                   TAG         IMAGE ID       CREATED       SIZE
mcr.microsoft.com/dotnet/framework/samples   dotnetapp   52c54f01bc20   3 weeks ago   8.03GB

第四步,Run一個asp.net webform示例容器:

docker run --name aspnet_sample --rm -it -d -p 8000:80 mcr.microsoft.com/dotnet/framework/samples:aspnetapp

需要注意的是,這裡映射到主機的端口是8000,需要在阿里雲ECS控制台的安全組裡為其開放入網規則。

在Windows Server 2019中,對容器支持localhost的訪問(在2019之前,只能通過容器IP或本機IP地址訪問),因此可以在ECS中直接通過瀏覽器訪問://localhost:8000

這時,從外部瀏覽器訪問公網IP地址:8000也可以訪問到這個ASP.NET應用程序了。

如果你想了解容器的具體IP,你可以使用下面的這個命令:

docker inspect -f "{{ .NetworkSettings.Networks.nat.IPAddress }}" aspnet_sample

 如果你想進入這個示例容器內部看看,你可以使用下面這個命令:

docker exec -it aspnet_sample powershell

進入這個容器的工作目錄(這裡是/inetpub/wwwroot),你會看到一堆ASP.NET WebForm的Release文件:

> docker exec -it aspnet_sample powershell
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.

PS C:\inetpub\wwwroot> ls

    Directory: C:\inetpub\wwwroot


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----         6/9/2021   9:35 AM                App_Start
d-----         6/9/2021   9:47 AM                bin
d-----         6/9/2021   9:35 AM                Content
d-----         6/9/2021   9:35 AM                fonts
d-----         6/9/2021   9:47 AM                obj
d-----         6/9/2021   9:35 AM                Properties
d-----         6/9/2021   9:35 AM                Scripts
......

你也可以在容器內部訪問localhost(默認80端口)驗證一下:

> iwr -useb http://localhost

StatusCode        : 200
StatusDescription : OK
Content           : ......
ParsedHtml        :
RawContentLength  : 5096

4 總結

本文介紹了Windows Container的基本概念、阿里雲ECS與ACK對Windows Container的支持,然後介紹了如何在阿里雲ECS(Windows Server 2019)上進行.NET 4.x應用的容器化部署運行。

下一篇,我們會自己通過編寫Dockerfile的方式來部署一個ASP.NET MVC應用程序到Docker上來體驗一下。