PluginBench
Skill
Pass
Audit score 90

docker

codewithmukesh/dotnet-claude-kit

Multi-stage Docker builds and containerization patterns for .NET 10 applications.

What is docker?

Guidance on containerizing .NET applications with Docker, covering multi-stage builds, non-root user configuration, layer caching, health checks, and Docker Compose setup. Use this when building Dockerfiles, optimizing image size, or setting up local development containers.

  • Multi-stage Dockerfile patterns separating build (SDK) and runtime (ASP.NET) stages
  • Non-root user configuration using built-in `app` user for security
  • Layer caching optimization by copying project files before source code
  • Health check endpoint patterns and orchestrator-level probe configuration
  • Docker Compose setup for local development with service dependencies and environment variables
  • .dockerignore templates to exclude build artifacts and unnecessary files

How to install docker

npx skills add https://github.com/codewithmukesh/dotnet-claude-kit --skill docker
Claude Code
Cursor
Windsurf
Cline

How to use docker

  1. 1.Create a Dockerfile with separate build and runtime stages using `mcr.microsoft.com/dotnet/sdk:10.0` and `mcr.microsoft.com/dotnet/aspnet:10.0`
  2. 2.Copy project files (.csproj) and run `dotnet restore` before copying source code to leverage layer caching
  3. 3.Add `USER app` in the runtime stage to run as non-root user
  4. 4.Create a `.dockerignore` file to exclude bin, obj, .git, and test directories
  5. 5.Add a lightweight `/health/live` endpoint in Program.cs for health checks
  6. 6.Set up `docker-compose.yml` with service dependencies, environment variables, and healthcheck configuration

Use cases

Good for
  • Creating optimized multi-stage Dockerfiles for .NET web APIs and worker services
  • Setting up Docker Compose for local development with PostgreSQL, Redis, and other dependencies
  • Implementing health check endpoints and configuring Compose/Kubernetes probes
  • Reducing image size by using ASP.NET runtime images instead of SDK images
  • Configuring non-root user execution and managing secrets via environment variables
Who it's for
  • Backend developers containerizing .NET applications
  • DevOps engineers optimizing Docker image builds and deployments
  • Teams using Docker Compose for local development environments
  • Developers working with Kubernetes or container orchestration

docker FAQ

Why use multi-stage builds instead of a single SDK image?

Multi-stage builds separate compilation (SDK image, ~900MB) from runtime (ASP.NET image, ~200MB), reducing final image size by 75% and removing unnecessary compilers from production.

Should I use HEALTHCHECK in the Dockerfile?

No. Standard .NET container images lack shell and curl, so in-image HEALTHCHECK commands fail. Instead, expose a `/health/live` endpoint and let Kubernetes `httpGet` probes or Docker Compose `healthcheck` call it from outside the container.

Why copy .csproj files before source code?

NuGet restore is cached as a separate layer. Copying only project files first means source code changes don't invalidate the dependency cache, speeding up rebuilds.

Can I run .NET containers as root?

No. .NET 8+ images include a built-in non-root `app` user. Always use `USER app` in production for security; running as root is a significant vulnerability.

What's the difference between this skill and container-publish?

This skill covers traditional Dockerfile-based containerization. Use container-publish for Dockerfile-less SDK publishing via `dotnet publish /t:PublishContainer`.

Full instructions (SKILL.md)

Source of truth, from codewithmukesh/dotnet-claude-kit.


name: docker description: > Docker containerization for .NET 10 applications. Covers multi-stage builds, .NET container images, non-root user configuration, health checks, and .dockerignore. Load this skill when containerizing an application with a Dockerfile, optimizing image size, setting up Docker Compose for local development, or when the user mentions "Docker", "Dockerfile", "container", "docker-compose", "image", "multi-stage", "non-root", ".dockerignore", or "container health check". For Dockerfile-less SDK publishing (dotnet publish /t:PublishContainer), load the container-publish skill instead.

Docker

Core Principles

  1. Multi-stage builds always — Separate build and runtime stages. Build in the SDK image, run in the ASP.NET runtime image.
  2. Non-root by default — .NET container images support USER app by default since .NET 8. Never run as root in production.
  3. Layer caching matters — Copy .csproj files and restore before copying source code. This caches NuGet dependencies across builds.
  4. Health probes at the orchestrator level — Expose a /health/live endpoint and let Kubernetes/Compose probe it. Chiseled and default aspnet images have no shell or curl, so in-image HEALTHCHECK commands have nothing to run with.

Patterns

Multi-Stage Dockerfile for Web API

# Stage 1: Build
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
WORKDIR /src

# Copy project files and restore (cached layer)
COPY ["src/MyApp.Api/MyApp.Api.csproj", "src/MyApp.Api/"]
COPY ["src/MyApp.Domain/MyApp.Domain.csproj", "src/MyApp.Domain/"]
COPY ["Directory.Build.props", "."]
COPY ["Directory.Packages.props", "."]
RUN dotnet restore "src/MyApp.Api/MyApp.Api.csproj"

# Copy everything and build
COPY . .
RUN dotnet publish "src/MyApp.Api/MyApp.Api.csproj" \
    -c Release \
    -o /app/publish \
    --no-restore

# Stage 2: Runtime
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime
WORKDIR /app

# Non-root user (default in .NET 8+ images)
USER app

COPY --from=build /app/publish .

EXPOSE 8080

ENTRYPOINT ["dotnet", "MyApp.Api.dll"]

Container Health Probes

Prefer orchestrator-level probes (Kubernetes livenessProbe, Compose healthcheck) over a Dockerfile HEALTHCHECK — the standard aspnet and chiseled images ship no shell, no curl, and no wget, so there is nothing inside the container to run the probe with. Point the orchestrator at /health/live:

# docker-compose — probe from outside the app process
services:
  api:
    healthcheck:
      test: ["CMD-SHELL", "wget -qO- http://localhost:8080/health/live || exit 1"]
      interval: 30s
      timeout: 3s
      retries: 3
# Note: CMD-SHELL requires a shell + wget in the image. Use a non-chiseled
# variant for this, or better: let Kubernetes httpGet probes do it —
# they run from the kubelet, needing nothing inside the image.

If you must have an in-image HEALTHCHECK, base the runtime stage on a non-chiseled image that includes wget — never re-run the app binary as the probe command; that starts a second instance instead of checking the first.

.dockerignore

**/.git
**/.vs
**/bin
**/obj
**/node_modules
**/Dockerfile*
**/docker-compose*
**/tests

Docker Compose for Local Development

Key .NET-specific concerns — pass connection strings via environment, use depends_on with health checks:

services:
  api:
    build:
      context: .
      dockerfile: src/MyApp.Api/Dockerfile
    ports:
      - "5000:8080"
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - ConnectionStrings__Default=Host=postgres;Database=myapp;Username=postgres;Password=postgres
      - ConnectionStrings__Redis=redis:6379
    depends_on:
      postgres:
        condition: service_healthy
  # Add postgres/redis services with healthcheck — standard boilerplate

Optimized Build with .slnx

For solutions with multiple projects, restore only the necessary projects.

FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
WORKDIR /src

# Copy solution and all project files
COPY *.slnx .
COPY Directory.Build.props .
COPY Directory.Packages.props .
COPY src/**/*.csproj ./src/

# Restore project structure
RUN for file in src/**/*.csproj; do \
    mkdir -p $(dirname $file) && mv $file $(dirname $file)/; \
    done
RUN dotnet restore

COPY . .
RUN dotnet publish src/MyApp.Api -c Release -o /app/publish --no-restore

Health Check Endpoint

// In Program.cs — lightweight health endpoint for Docker
app.MapGet("/health/live", () => Results.Ok("healthy"))
    .ExcludeFromDescription();

Anti-patterns

Don't Use SDK Image for Runtime

# BAD — SDK image is 900MB+, includes compilers
FROM mcr.microsoft.com/dotnet/sdk:10.0
COPY . .
RUN dotnet run

# GOOD — separate build and runtime, runtime image is ~200MB
FROM mcr.microsoft.com/dotnet/aspnet:10.0

Don't Copy Everything Before Restore

# BAD — any source change invalidates the NuGet cache
COPY . .
RUN dotnet restore

# GOOD — copy only project files first, then restore
COPY ["src/MyApp.Api/MyApp.Api.csproj", "src/MyApp.Api/"]
RUN dotnet restore "src/MyApp.Api/MyApp.Api.csproj"
COPY . .

Don't Run as Root

# BAD — running as root (security risk)
FROM mcr.microsoft.com/dotnet/aspnet:10.0
COPY --from=build /app .
ENTRYPOINT ["dotnet", "MyApp.Api.dll"]

# GOOD — use the built-in non-root user
FROM mcr.microsoft.com/dotnet/aspnet:10.0
USER app
COPY --from=build /app .
ENTRYPOINT ["dotnet", "MyApp.Api.dll"]

Decision Guide

ScenarioRecommendation
Web API containerMulti-stage build with aspnet runtime image
Worker serviceMulti-stage build with dotnet/runtime image
Local developmentDocker Compose with service dependencies
CI buildsMulti-stage build (self-contained)
Image size optimizationUse Alpine variant + trimming for small images
Health monitoring/health endpoint + orchestrator probe (K8s httpGet / Compose healthcheck)
SecretsEnvironment variables or mounted secrets, never in image