Docker Containers & Deployment
Master containerizing .NET applications — multi-stage builds, image optimization, container orchestration, and production Docker best practices.
50 min•By Priygop Team•Last updated: Feb 2026
Multi-Stage Docker Builds
- Stage 1 — Build: Use mcr.microsoft.com/dotnet/sdk:8.0 — restore, build, publish. SDK image is large (~700MB) but has all build tools
- Stage 2 — Runtime: Use mcr.microsoft.com/dotnet/aspnet:8.0 — copy published output only. Runtime image is small (~200MB)
- Stage 3 — Chiseled/Alpine: Use mcr.microsoft.com/dotnet/aspnet:8.0-alpine or chiseled images — ultra-small (~100MB), no shell, reduced attack surface
- Layer Optimization: COPY *.csproj first, then RUN dotnet restore, then COPY everything and build — Docker caches restore layer when only code changes
- AOT Publishing: dotnet publish -p:PublishAot=true creates native binary — no .NET runtime needed, ~30MB image with scratch base, sub-millisecond startup
- Security: Run as non-root user (USER app), scan images with Trivy, pin base image digests, never include development certificates or secrets
Container Orchestration
- Docker Compose: Multi-container local development — API + database + Redis + message broker. docker-compose up starts the entire stack
- Kubernetes: Production orchestration — Deployments, Services, Ingress, ConfigMaps, Secrets. Use Helm charts for repeatable deployments
- Health Checks: Configure /health/ready (dependencies ready) and /health/live (process alive) — Kubernetes uses these for readiness/liveness probes
- Resource Limits: Set CPU and memory limits in K8s manifests — prevents one container from consuming all node resources. .NET respects cgroup limits
- Horizontal Pod Autoscaler: Scale pods based on CPU, memory, or custom metrics — handles traffic spikes automatically. Set min/max replica counts
- Rolling Updates: Zero-downtime deployments — Kubernetes gradually replaces old pods with new ones. Set maxSurge and maxUnavailable for controlled rollout