Multi-Stage Dockerization with .NET Chiseled Ubuntu Images
1Concept
Microsoft .NET 'Chiseled' Ubuntu container images contain no package managers (apt), no shells (bash/sh), and run as non-root, shrinking Docker images to < 50MB and eliminating 99% of CVE vulnerabilities.
2Architecture Diagram
[ Stage 1: Build Image (mcr.microsoft.com/dotnet/sdk:9.0) ]
│ Compiles application & publishes output
▼
[ Stage 2: Runtime Image (mcr.microsoft.com/dotnet/nightly/aspnet:9.0-chiseled) ]
├── No root user
├── No shell / package manager (Ultra-Secure!)
└── Binary Size: ~45MB3Code Example
C# 13 & .NET 9
using System;
public class DockerfileArchitectureDemo
{
public const string ProductionDockerfile = @"
# Stage 1: Build
FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
WORKDIR /src
COPY ["App.csproj", "./"]
RUN dotnet restore
COPY . .
RUN dotnet publish -c Release -o /app/publish /p:UseAppHost=false
# Stage 2: Ultra-Lean Chiseled Runtime
FROM mcr.microsoft.com/dotnet/aspnet:9.0-chiseled AS runtime
WORKDIR /app
COPY --from=build /app/publish .
USER $APP_UID
ENTRYPOINT ["dotnet", "App.dll"]
";
public static void Main()
{
Console.WriteLine("--- Production Multi-Stage Chiseled Dockerfile ---");
Console.WriteLine(ProductionDockerfile.Trim());
}
}4Expected Output
--- Production Multi-Stage Chiseled Dockerfile --- # Stage 1: Build FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build WORKDIR /src COPY ["App.csproj", "./"] RUN dotnet restore COPY . . RUN dotnet publish -c Release -o /app/publish /p:UseAppHost=false # Stage 2: Ultra-Lean Chiseled Runtime FROM mcr.microsoft.com/dotnet/aspnet:9.0-chiseled AS runtime WORKDIR /app COPY --from=build /app/publish . USER $APP_UID ENTRYPOINT ["dotnet", "App.dll"]
5Key Takeaways
- ✓Always use multi-stage Docker builds to keep build tools out of production containers.
- ✓Use `mcr.microsoft.com/dotnet/aspnet:9.0-chiseled` for rock-solid security compliance.
- ✓Runs as non-root user `$APP_UID` automatically.