Docker  

What are the best ways to optimize Docker images

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.

  • Place less-frequently changing steps (like dotnet restore) early.

  • Frequently changing files (like source code) later.

βœ… 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

  • Use docker image prune and docker system prune to clean old layers.

  • Scan with:

    docker scan myapp:latest
    

βœ… 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.