Here are the best, practical, and production-grade ways to optimize Docker images β especially for .NET, Node, or microservices running in Kubernetes or Azure π
π 1. Use Multi-Stage Builds
Only copy what you need into the final image.
Example (.NET 8):
# Stage 1: Build
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /app
COPY . .
RUN dotnet publish -c Release -o out
# Stage 2: Runtime (small)
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
COPY --from=build /app/out .
ENTRYPOINT ["dotnet", "MyApp.dll"]
β
Removes SDK tools and reduces image size by 70%+
βοΈ 2. Use Lightweight Base Images
Prefer:
alpine (e.g., mcr.microsoft.com/dotnet/aspnet:8.0-alpine)
distroless (Googleβs minimal image, no shell)
Avoid ubuntu or debian unless needed.
β
Saves 100β300 MB instantly.
π¦ 3. Copy Only What You Need
Avoid copying everything:
COPY ["MyApp.csproj", "./"]
RUN dotnet restore
COPY . .
Or use .dockerignore to skip unnecessary files (like node_modules, .git, logs, etc.)
β
Smaller build context β faster build.
π 4. Leverage Layer Caching
Docker caches each layer β order matters.
β
Speeds up rebuilds drastically.
π§Ή 5. Clean Temporary Files
After install commands, remove caches:
RUN apt-get update && apt-get install -y curl \
&& rm -rf /var/lib/apt/lists/*
β
Keeps image lean and clean.
π 6. Use Non-Root User
For security and lightweight permission layers:
RUN adduser --disabled-password appuser
USER appuser
β
Prevents privilege escalation in containers.
π§± 7. Combine RUN Commands
Each RUN adds a new layer. Combine them:
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
β
Fewer layers β smaller image.
π§° 8. Use Docker BuildKit
Enable it:
export DOCKER_BUILDKIT=1
docker build .
β
Builds are faster, parallelized, and cache-efficient.
π§ 9. Compress and Scan
β
Removes vulnerabilities and bloat.
βοΈ 10. Push Optimized Images
Before pushing to ACR or Docker Hub:
docker build --squash -t myapp:latest .
docker push myregistry.azurecr.io/myapp:latest
β
βSquashβ merges layers for minimal size.
π Bonus Tips for .NET Core
Use ReadyToRun compilation for faster startup:
dotnet publish -c Release -p:PublishReadyToRun=true
Trim unused assemblies:
dotnet publish -c Release -p:PublishTrimmed=true
β
Perfect for microservices deployed in AKS or Azure VM.