传统.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中直接通过浏览器访问:http://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上来体验一下。