关于 container-publish
一项介绍如何通过 .NET 10 SDK 将 .NET 应用发布为 OCI 容器镜像的技能,涵盖 MSBuild 配置、镜像类型、架构目标及无需 Docker 的归档输出。
主要功能
- 01使用 dotnet publish 构建 OCI 镜像
- 02通过 MSBuild 属性配置镜像
- 03选择 chiseled 等镜像类型
- 04发布多架构镜像
- 05将镜像导出为 tar 包
适用场景
- 01为生产环境打包 ASP.NET Core API
- 02发布 x64 和 arm64 镜像
- 03生成供 CI 扫描的容器归档
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ codewithmukesh/ dotnet-claude-kit --skill container-publish安装后在 Claude Code 中输入/container-publish确认已加载。
详细介绍
容器发布(无需 Dockerfile)
核心原则
- 无需 Dockerfile — .NET 10 SDK 可直接通过
dotnet publish /t:PublishContainer构建符合 OCI 标准的容器镜像。无需编写或维护 Dockerfile。 - 生产环境使用 Chiseled 镜像 — 使用
noble-chiseled基础镜像:没有 Shell、没有包管理器,仅包含 7 个 Linux 组件,而非 100 多个。攻击面最小。 - 默认以非 root 用户运行 — .NET 10 容器镜像会自动以
app用户运行。生产环境中绝不要切换为 root。 - 在 .csproj 中配置 — 所有容器设置都是 MSBuild 属性,与项目一同进行版本控制。无需担心单独的文件与项目配置不一致。
常用模式
最简容器发布
无需更改项目文件。直接发布:
dotnet publish /t:PublishContainer --os linux --arch x64
这会使用默认的 aspnet:10.0 基础镜像,在本地 Docker 守护进程中创建容器镜像。
可用于生产环境的 .csproj 配置
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ContainerRepository>mycompany/myapp-api</ContainerRepository>
<ContainerFamily>noble-chiseled</ContainerFamily>
</PropertyGroup>
<ItemGroup>
<ContainerPort Include="8080" Type="tcp" />
<ContainerEnvironmentVariable Include="ASPNETCORE_HTTP_PORTS" Value="8080" />
<ContainerEnvironmentVariable Include="DOTNET_EnableDiagnostics" Value="0" />
<ContainerLabel Include="org.opencontainers.image.vendor" Value="MyCompany" />
</ItemGroup>
</Project>
发布到注册表
先使用 docker login 进行身份验证,然后指定注册表:
# GitHub Container Registry
docker login ghcr.io
dotnet publish /t:PublishContainer --os linux --arch x64 \
-p ContainerRegistry=ghcr.io \
-p ContainerImageTag=1.0.0
# Azure Container Registry
az acr login --name myregistry
dotnet publish /t:PublishContainer --os linux --arch x64 \
-p ContainerRegistry=myregistry.azurecr.io
# Docker Hub (requires username prefix in repository)
dotnet publish /t:PublishContainer --os linux --arch x64 \
-p ContainerRegistry=docker.io \
-p ContainerRepository=myuser/myapp
多架构镜像
通过一次发布为多个平台构建镜像:
<PropertyGroup>
<RuntimeIdentifiers>linux-x64;linux-arm64</RuntimeIdentifiers>
<ContainerRuntimeIdentifiers>linux-x64;linux-arm64</ContainerRuntimeIdentifiers>
</PropertyGroup>
dotnet publish /t:PublishContainer
这会生成 OCI 镜像索引,注册表会自动提供适合的架构。
多个标签
# Bash — note the quoting for semicolons
dotnet publish /t:PublishContainer --os linux --arch x64 \
-p ContainerImageTags='"1.0.0;latest"'
也可以在项目文件中配置:
<ContainerImageTags>1.0.0;latest</ContainerImageTags>
保存为 Tarball(无需 Docker)
构建机器无需容器运行时。适用于 CI 扫描:
dotnet publish /t:PublishContainer --os linux --arch x64 \
-p ContainerArchiveOutputPath=./images/myapp.tar.gz
# Scan with Trivy before pushing
trivy image --input ./images/myapp.tar.gz
Chiseled 镜像变体
| 容器系列 | 用途 | Shell | 大小 |
|---|---|---|---|
| (默认) | 通用(Debian) | 有 | ~220 MB |
noble-chiseled | 生产环境(无 Shell) | 无 | ~110 MB |
noble-chiseled-extra | 支持本地化的生产环境(ICU) | 无 | ~120 MB |
alpine | 体积小,带 Shell | 有 | ~112 MB |
<ContainerFamily>noble-chiseled</ContainerFamily>
<ContainerFamily>noble-chiseled-extra</ContainerFamily>
对于 Native AOT,SDK 会自动选择 chiseled-aot:
<PublishAot>true</PublishAot>
使用 GitHub Actions 的 CI/CD
jobs:
publish:
runs-on: ubuntu-latest
permissions:
packages: write
steps:
- uses: actions/checkout@v5
- uses: actions/setup-dotnet@v5
with:
dotnet-version: '10.0.x'
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- run: |
dotnet publish src/MyApp.Api/MyApp.Api.csproj \
/t:PublishContainer --os linux --arch x64 \
-p ContainerRegistry=ghcr.io \
-p ContainerRepository=${{ github.repository_owner }}/myapp \
-p ContainerImageTag=${{ github.sha }}
反模式
不要使用已弃用的属性名称
<ContainerImageName>myapp</ContainerImageName>
<ContainerRepository>myapp</ContainerRepository>
不要使用 PublishProfile=DefaultContainer
# BAD — old approach, inconsistent across project types
dotnet publish -p:PublishProfile=DefaultContainer
# GOOD — use the MSBuild target directly
dotnet publish /t:PublishContainer
不要忘记指定 Linux 目标平台
# BAD on Windows — may produce a Windows container
dotnet publish /t:PublishContainer
# GOOD — explicitly target Linux
dotnet publish /t:PublishContainer --os linux --arch x64
推送前不要忘记进行身份验证
# BAD — fails with CONTAINER1013 error
dotnet publish /t:PublishContainer -p ContainerRegistry=ghcr.io
# GOOD — authenticate first
docker login ghcr.io
dotnet publish /t:PublishContainer -p ContainerRegistry=ghcr.io
需要 OS 包时不要使用 SDK 发布
<ContainerBaseImage>myregistry/custom-base:1.0</ContainerBaseImage>
选择指南
| 场景 | 建议 |
|---|---|
| 标准 ASP.NET Core API | 使用 SDK 容器发布和 noble-chiseled |
| Worker 服务/控制台应用 | 使用 SDK 容器发布(.NET 10 原生支持) |
| 需要原生 OS 包 | 使用 Dockerfile(或自定义基础镜像 + SDK 发布) |
| Azure Functions | 使用 Dockerfile(SDK 发布不支持) |
| CI 环境没有 Docker 守护进程 | 使用 ContainerArchiveOutputPath 输出 Tarball |
| 多架构部署(x64 + arm64) | 使用 ContainerRuntimeIdentifiers 属性 |
| 生产镜像体积 | 使用 noble-chiseled(~110 MB)或 Native AOT(~10 MB) |
| 本地开发 | 使用 dotnet publish /t:PublishContainer --os linux --arch x64 |
| 推送到注册表 | 使用 ContainerRegistry + docker login |
评论
支持 Markdown