mcpField
C
container-publish

container-publish

github.com/codewithmukesh云与 DevOps7912.9k 次安装12 周前更新
代码仓库

关于 container-publish

一项介绍如何通过 .NET 10 SDK 将 .NET 应用发布为 OCI 容器镜像的技能,涵盖 MSBuild 配置、镜像类型、架构目标及无需 Docker 的归档输出。

主要功能

  1. 01使用 dotnet publish 构建 OCI 镜像
  2. 02通过 MSBuild 属性配置镜像
  3. 03选择 chiseled 等镜像类型
  4. 04发布多架构镜像
  5. 05将镜像导出为 tar 包

适用场景

  1. 01为生产环境打包 ASP.NET Core API
  2. 02发布 x64 和 arm64 镜像
  3. 03生成供 CI 扫描的容器归档

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/codewithmukesh/dotnet-claude-kit --skill container-publish

安装后在 Claude Code 中输入/container-publish确认已加载。

详细介绍

容器发布(无需 Dockerfile)

核心原则

  1. 无需 Dockerfile — .NET 10 SDK 可直接通过 dotnet publish /t:PublishContainer 构建符合 OCI 标准的容器镜像。无需编写或维护 Dockerfile。
  2. 生产环境使用 Chiseled 镜像 — 使用 noble-chiseled 基础镜像:没有 Shell、没有包管理器,仅包含 7 个 Linux 组件,而非 100 多个。攻击面最小。
  3. 默认以非 root 用户运行 — .NET 10 容器镜像会自动以 app 用户运行。生产环境中绝不要切换为 root。
  4. 在 .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