DEV Community

Darshan Vasani
Darshan Vasani Subscriber

Posted on • Edited on

🐳 Docker Image Optimization Guide β€” The Ultimate Cheat Sheet πŸš€

🐳 Docker Image Optimization Guide β€” The Ultimate Cheat Sheet πŸš€

Optimize your Docker images for faster builds, smaller size, better caching, and production readiness. Let’s go!


🧱 1. Use a Small & Specific Base Image πŸ₯

βœ… Do This:

# Use lightweight Alpine variant FROM node:20-alpine 
Enter fullscreen mode Exit fullscreen mode

❌ Avoid This:

# Heavy image β€” more layers, longer build times FROM ubuntu 
Enter fullscreen mode Exit fullscreen mode

πŸ“ Why?

  • Smaller base = smaller image.
  • Alpine images are ~5MB vs Ubuntu’s ~100MB.
  • Smaller size = faster download, upload, deploy.

πŸͺœ 2. Order Instructions for Layer Caching πŸ”

βœ… Do This:

# Caches `npm install` unless package.json changes COPY package*.json ./ RUN npm install # Copy rest of the source after deps are installed COPY . . 
Enter fullscreen mode Exit fullscreen mode

❌ Avoid This:

COPY . . # πŸ‘Ž invalidates cache if any file changes RUN npm install 
Enter fullscreen mode Exit fullscreen mode

πŸ“ Why?

Docker caches layers. Changing a later step invalidates all subsequent layers. Put stable steps early for faster rebuilds.


🧹 3. Remove Unnecessary Files with .dockerignore 🚫

βœ… Example .dockerignore:

node_modules Dockerfile .dockerignore .git npm-debug.log 
Enter fullscreen mode Exit fullscreen mode

πŸ“ Why?

It prevents Docker from copying unnecessary files into the build context. Less context = faster build and smaller image.


πŸ—οΈ 4. Use Multi-Stage Builds πŸ§ͺ

βœ… Example:

# Stage 1: Builder FROM node:20-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm install COPY . . # Stage 2: Runtime FROM node:20-alpine WORKDIR /app COPY --from=builder /app . EXPOSE 8000 CMD ["npm", "start"] 
Enter fullscreen mode Exit fullscreen mode

πŸ“ Why?

  • Separate build dependencies from runtime.
  • Final image contains only what’s needed to run the app.
  • Reduces image size by up to 70%.

🧼 5. Remove Unused Dependencies 🧹

βœ… Use --production for Node.js:

RUN npm ci --only=production 
Enter fullscreen mode Exit fullscreen mode

OR

npm prune --production 
Enter fullscreen mode Exit fullscreen mode

πŸ“ Why?

Avoid bundling dev tools and test libraries into your production image.


πŸ“¦ 6. Combine RUN Commands πŸ”—

βœ… Do This:

RUN apk add --no-cache bash curl && \  rm -rf /var/cache/apk/* 
Enter fullscreen mode Exit fullscreen mode

❌ Don’t Do:

RUN apk add bash RUN apk add curl 
Enter fullscreen mode Exit fullscreen mode

πŸ“ Why?

Each RUN creates a layer. Combining reduces total layers = smaller image size.


πŸ‡ 7. Use --no-cache for Package Managers πŸ“₯

βœ… Alpine:

RUN apk add --no-cache curl 
Enter fullscreen mode Exit fullscreen mode

βœ… APT (Debian/Ubuntu):

RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/* 
Enter fullscreen mode Exit fullscreen mode

πŸ“ Why?

Avoids unnecessary cache files and reduces image size.


πŸ” 8. Avoid Root User (Security Best Practice) πŸ”’

# Create a non-root user RUN addgroup -S appgroup && adduser -S appuser -G appgroup USER appuser 
Enter fullscreen mode Exit fullscreen mode

πŸ“ Why?

Running as root inside containers is risky. Use non-root users for security.


πŸͺ„ 9. Clean Up Temporary Files 🧼

RUN npm install && \  npm cache clean --force 
Enter fullscreen mode Exit fullscreen mode

πŸ“ Why?

Removes package cache after install to reduce bloat.


πŸͺ› 10. Use Specific Tags (Not latest) 🎯

FROM node:20.11.1-alpine 
Enter fullscreen mode Exit fullscreen mode

πŸ“ Why?

Using latest can break builds if the base image updates and introduces changes. Always pin versions for reliability.


πŸ”’ 11. Scan for Vulnerabilities 🧬

docker scan my-node-app 
Enter fullscreen mode Exit fullscreen mode

Or use:

  • Docker Scout
  • Trivy (Aqua Security)
  • Snyk

πŸ§ͺ 12. Analyze Image Size and Layers πŸ”

docker image inspect my-node-app docker history my-node-app 
Enter fullscreen mode Exit fullscreen mode

Or use tools like:

  • Dive: dive my-node-app
  • DockerSlim: docker-slim build my-node-app

🧠 Final Pro Tips πŸ’‘

Tip Benefit
Use npm ci instead of npm install Faster and more reliable
Group COPY steps wisely Better cache usage
Avoid adding .env or secrets Security risk
Label images (LABEL maintainer=...) Better documentation
Run production builds with NODE_ENV=production Removes dev dependencies

πŸ“Œ Sample Optimized Dockerfile for Node.js App

# πŸ‘· Stage 1: Build FROM node:20-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . # ✨ Stage 2: Runtime FROM node:20-alpine WORKDIR /app COPY --from=builder /app . ENV NODE_ENV=production RUN npm prune --production EXPOSE 8000 CMD ["npm", "start"] 
Enter fullscreen mode Exit fullscreen mode

Top comments (0)