container-publish
Dockerfile-less containerization using the .NET 10 SDK container publishing feature. Covers MSBuild properties, chiseled images, multi-arch builds, and registry publishing — all without writing a Dockerfile. Load this skill when the user wants to containerize without a Dockerfile, or mentions "dotnet publish container", "PublishContainer", "ContainerRepository", "ContainerFamily", "chiseled", "distroless", "container publish", "SDK container", "no Dockerfile", or "containerize without Docker".
Resumen
Container Publishing (No Dockerfile)
Core Principles
- No Dockerfile needed — The .NET 10 SDK builds OCI-compliant container images directly from
dotnet publish /t:PublishContainer. No Dockerfile to write or maintain. - Chiseled images for production — Use
noble-chiseledbase images: no shell, no package manager, 7 Linux components vs 100+. Smallest attack surface. - Non-root by default — .NET 10 container images run as the
appuser automatically. Never override to root in production. - Configuration in the .csproj — All container settings are MSBuild properties, versioned with your project. No separate files to drift.
Patterns
Minimal Container Publish
No project file changes needed. Just publish:
dotnet publish /t:PublishContainer --os linux --arch x64This creates a container image in your local Docker daemon using the default aspnet:10.0 base image.
Production-Ready .csproj Configuration
<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>Publishing to a Registry
Authenticate with docker login first, then specify the registry:
# 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/myappMulti-Architecture Images
Build images for multiple platforms with a single publish:
<PropertyGroup>
<RuntimeIdentifiers>linux-x64;linux-arm64</RuntimeIdentifiers>
<ContainerRuntimeIdentifiers>linux-x64;linux-arm64</ContainerRuntimeIdentifiers>
</PropertyGroup>dotnet publish /t:PublishContainerThis produces an OCI Image Index — registries serve the correct architecture automatically.
Multiple Tags
# Bash — note the quoting for semicolons
dotnet publish /t:PublishContainer --os linux --arch x64 \
-p ContainerImageTags='"1.0.0;latest"'Or in the project file:
<ContainerImageTags>1.0.0;latest</ContainerImageTags>Save as Tarball (No Docker Required)
No container runtime needed on the build machine. Useful for CI scanning:
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.gzChiseled Image Variants
| ContainerFamily | Use Case | Shell | Size |
|---|---|---|---|
| (default) | General purpose (Debian) | Yes | ~220 MB |
noble-chiseled | Production (no shell) | No | ~110 MB |
noble-chiseled-extra | Production with localization (ICU) | No | ~120 MB |
alpine | Small size, has shell | Yes | ~112 MB |
<ContainerFamily>noble-chiseled</ContainerFamily>
<ContainerFamily>noble-chiseled-extra</ContainerFamily>For Native AOT, the SDK auto-selects chiseled-aot:
<PublishAot>true</PublishAot>
CI/CD with GitHub Actions
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 }}Anti-patterns
Don't Use the Deprecated Property Names
<ContainerImageName>myapp</ContainerImageName>
<ContainerRepository>myapp</ContainerRepository>Don't Use PublishProfile=DefaultContainer
# BAD — old approach, inconsistent across project types
dotnet publish -p:PublishProfile=DefaultContainer
# GOOD — use the MSBuild target directly
dotnet publish /t:PublishContainerDon't Forget to Target Linux
# BAD on Windows — may produce a Windows container
dotnet publish /t:PublishContainer
# GOOD — explicitly target Linux
dotnet publish /t:PublishContainer --os linux --arch x64Don't Skip Authentication Before Push
# 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.ioDon't Use SDK Publishing When You Need OS Packages
<ContainerBaseImage>myregistry/custom-base:1.0</ContainerBaseImage>Decision Guide
| Scenario | Recommendation |
|---|---|
| Standard ASP.NET Core API | SDK container publishing with noble-chiseled |
| Worker service / console app | SDK container publishing (native .NET 10 support) |
| Needs native OS packages | Dockerfile (or custom base image + SDK publishing) |
| Azure Functions | Dockerfile (not supported by SDK publishing) |
| CI without Docker daemon | Tarball output with ContainerArchiveOutputPath |
| Multi-arch deployment (x64 + arm64) | ContainerRuntimeIdentifiers property |
| Production image size | noble-chiseled (~110 MB) or Native AOT (~10 MB) |
| Local development | dotnet publish /t:PublishContainer --os linux --arch x64 |
| Registry push | ContainerRegistry + docker login |
Archivos 1 archivo
Instálala a mano
Deska ejecuta esto por ti, para cada agente que elijas. Para ejecutarlo tú en una terminal:
npx skills add codewithmukesh/dotnet-claude-kit --skill container-publishMás de codewithmukesh
- clean-architecturecodewithmukeshClean Architecture for .NET applications. Covers the 4-project layout (Domain, Application, Infrastructure, Api), dependency inversion, use case handlers, domain entities with behavior, and infrastructure as a plugin. Load this skill when building a project with Clean Architecture, discussing layered architecture, dependency inversion, use cases, or when the architecture-advisor recommends Clean Architecture.2,200 instalaciones en skills.sh0
- architecture-advisorcodewithmukeshArchitecture selection advisor for .NET applications. Asks structured questions about domain complexity, team size, system lifetime, compliance, and integration needs, then recommends the best-fit architecture: Vertical Slice, Clean Architecture, DDD + Clean Architecture, or Modular Monolith. Load this skill when the user asks "which architecture", "choose architecture", "set up project", "new project", "architecture decision", "restructure", or "how should I organize". Always load BEFORE any architecture-specific skill.2,100 instalaciones en skills.sh0
- authenticationcodewithmukeshAuthentication and authorization for ASP.NET Core. Covers JWT bearer tokens, OpenID Connect, ASP.NET Identity, authorization policies, role and claim-based authorization, and API key authentication. Load this skill when implementing login, protecting endpoints, designing authorization rules, or when the user mentions "auth", "JWT", "bearer token", "OIDC", "OpenID Connect", "Identity", "claims", "roles", "authorize", "RequireAuthorization", "API key", or "cookie auth".2,100 instalaciones en skills.sh0
- ci-cdcodewithmukeshCI/CD pipelines for .NET applications. Covers GitHub Actions and Azure DevOps YAML pipelines with build, test, publish, and deploy stages. Load this skill when setting up continuous integration, automated testing, deployment workflows, or when the user mentions "CI/CD", "pipeline", "GitHub Actions", "Azure DevOps", "workflow", "deploy", "build pipeline", "publish", "NuGet push", "release", or "continuous integration".2,100 instalaciones en skills.sh0
- configurationcodewithmukeshConfiguration patterns for .NET 10 applications. Covers the Options pattern, IOptionsSnapshot vs IOptions, secrets management, and environment-based configuration. Load this skill when setting up application configuration, managing secrets, binding configuration sections, or when the user mentions "configuration", "appsettings", "Options pattern", "IOptions", "IOptionsSnapshot", "secrets", "user secrets", "environment variables", "connection string", or "config binding".2,100 instalaciones en skills.sh0