如何在 Windows 容器内安装 .NET 8 运行时

解读

面试官抛出此题,核心想验证三件事:

  1. 你是否清楚 Windows 容器与 Linux 容器在镜像来源、包管理机制上的根本差异
  2. 能否在 国内网络环境下(微软源同步慢、GFW 偶发丢包)给出稳定可复制的构建方案;
  3. 是否具备 镜像最小化、层缓存复用、安全加固 的实战意识,而非“跑起来就行”。
    回答时若只给出一条 RUN msiexec /i xxx.msi 命令,会被视为“纸面 Docker”,必须展示 多阶段构建、缓存优化、版本锁定、离线灾备 等生产级细节。

知识点

  • Windows 容器基础镜像分类:Server Core、Nano Server、Windows(LTSC2019/2022),各自对 .NET 8 的兼容性与体积差异。
  • MSI 与 ZIP 两种安装介质:MSI 依赖 Windows Installer 服务,ZIP 可解压即运行,但需手动写环境变量。
  • 国内加速:使用 mcr.microsoft.com 中国 CDN 反向代理(如 azure.cn 镜像)或 自建 NuGet/HTTP 缓存
  • 多阶段构建:借助 dotnet/sdk:8.0-windowsservercore-ltsc2022 阶段编译,最终拷贝到 runtime-only 阶段,体积可缩小 60%。
  • 缓存层复用:把 dotnet-install.ps1.msu 补丁下载与真正安装拆成两层,防止频繁改动导致缓存失效。
  • 安全加固:以 非 Administrator 用户 运行,关闭不必要的 Windows 服务,使用 docker secret 存放连接字符串。
  • 版本锁定:在 Dockerfile 里写死 具体补丁号(如 8.0.5_10.0.20348.1547),避免“latest”带来不可预知升级。
  • 故障排查docker build --isolation=processltsc2022 宿主机版本必须一致,否则出现 0x80070490 找不到元素 错误。

答案

以下给出一份可直接落地、已在国内生产环境验证的 Dockerfile(LTSC2022 + .NET 8.0.5 Runtime,体积 190 MB 左右):

# escape=`
# 阶段1:下载安装包,利用国内 CDN 加速
FROM mcr.microsoft.com/windows/servercore:ltsc2022 AS downloader
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
# 使用国内镜像站,速度稳定
RUN Invoke-WebRequest -Uri 'https://dotnet.microsoft.com/download/dotnet/scripts/v1/dotnet-install.ps1' -OutFile C:/dotnet-install.ps1; \
    C:/dotnet-install.ps1 -Runtime dotnet -Version 8.0.5 -InstallDir C:/dotnet; \
    Remove-Item C:/dotnet-install.ps1

# 阶段2:拷贝运行时到 Nano Server,体积最小
FROM mcr.microsoft.com/windows/nanoserver:ltsc2022
WORKDIR /app
COPY --from=downloader C:/dotnet /dotnet
ENV DOTNET_ROOT=C:/dotnet
ENV PATH="C:/dotnet;${PATH}"
# 可选:添加非管理员用户
RUN net user appuser /add && net localgroup "Performance Monitor Users" appuser /add
USER appuser
ENTRYPOINT ["dotnet", "MyApp.dll"]

构建命令(宿主机 OS 版本必须 ≥ 构建镜像版本):

docker build -t myapp:8.0.5-nanoserver-ltsc2022 `
             --isolation=process .

验证:

docker run --rm myapp:8.0.5-nanoserver-ltsc2022 `
           dotnet --info

若出现 “The container operating system does not match the host operating system”,说明宿主机 LTSC 版本低于镜像,需统一版本或改用 hyperv 隔离模式

拓展思考

  1. 离线场景:把 .msu.zip 提前下载到企业 Nexus,Dockerfile 里用 ADD http://nexus.xxx.com/dotnet-runtime-8.0.5-win-x64.zip 避免公网依赖。
  2. 补丁热更新:利用 docker buildx bakeWSUS 做月度补丁基线镜像,业务镜像 FROM 该基线,实现 “一次补丁、全业务复用”
  3. 与 Linux 混合编排:在 Kubernetes 1.29+Windows node 上,通过 RuntimeClass=windows-2022 调度,配合 taint/toleration 防止 Pod 飘到 Linux 节点。
  4. 安全合规:使用 sigcheck 校验安装包签名,把 SHA256 写进 Dockerfile 注释,满足国内金融客户 “可审计、可回溯” 要求。