Phase 30 of 30 · Topic 30.1

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: ~45MB

3Code 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.