DEV Community

Cover image for From 1.5GB to 200MB: How I Slimmed Down My Docker Image Like a Pro πŸš€
Mai Chi Bao
Mai Chi Bao

Posted on

From 1.5GB to 200MB: How I Slimmed Down My Docker Image Like a Pro πŸš€

A real journey of "less is more" in Docker 🐳


πŸ“š Table of Contents


🎯 The Problem: Bloated Docker Image

A few weeks ago, I built a Docker image for my personal portfolio project (a React app). Everything worked fine β€” until I checked the size...

πŸ’£ 1.5 GB! For a static frontend app?!

I realized this could slow down deployment, consume more storage, and make CI/CD pipelines sluggish. I had to fix this.


πŸ” The Investigation

When I looked into my Docker setup, I noticed some rookie mistakes:

  • I didn’t have a .dockerignore file πŸ˜…
  • I was using only a single-stage build
  • The base image was node:18-alpine, which seemed fine but not optimal for production delivery
  • I was copying everything (including node_modules, .git, and build files) into the image

This is my previous Dockerfile:

  # Use official Node image
  FROM node:18-alpine
  # Set working directory
  WORKDIR /app
  # Copy dependency files first (for better Docker caching)
  COPY package.json package-lock.json ./
  # Install dependencies
  RUN npm ci
  # Copy rest of the application
  COPY . .
  # Build the React app
  RUN npm run build
  # Install a lightweight static server
  RUN npm install -g serve 
  # Expose port
  EXPOSE 3000
  # Serve the static build
  CMD ["serve", "-s", "build", "-l", "3000"]
Enter fullscreen mode Exit fullscreen mode

It was time to clean house.


🧠 The Solution Explained

1. Add dockerignore

Think of .dockerignore as .gitignore for Docker. Without it, Docker copies everything from your working directory β€” including huge folders like:

  • node_modules/
  • .git/
  • build/
  • *.md docs

I added this .dockerignore:

  node_modules/
  npm-debug.log
  .git
  .gitignore
  Dockerfile
  docker-compose.yml
  build/
  dist/
  .env
  *.md
Enter fullscreen mode Exit fullscreen mode

πŸ‘‰ Result: Way less junk copied into the image = faster build time + smaller size


2. Use Multi stage Builds

Instead of one bloated Dockerfile, I split it into two stages:

  1. Builder Stage: Installs dependencies and runs the build
  2. Production Stage: Copies only what’s needed to serve the app
  # Stage 1: Build
  FROM node:18-slim AS builder
  WORKDIR /app
  COPY package*.json ./
  RUN npm ci --only=production
  COPY . .
  RUN npm run build

  # Stage 2: Serve
  FROM node:18-slim
  WORKDIR /app
  COPY --from=builder /app/build ./build
  RUN npm install -g serve
  EXPOSE 3000
  CMD ["serve", "-s", "build", "-l", "3000"]
Enter fullscreen mode Exit fullscreen mode

πŸ‘‰ Result: No dev dependencies or source code in the final image. Just the build output. Lean & clean.


3. Choose Lighter Base Images

Originally I used node:18-alpine. It’s small but sometimes causes compatibility issues with native modules.

I switched to node:18-slim, which is slightly larger than Alpine but more stable for multi-stage builds and still much smaller than the full Node image.

πŸ‘‰ Result: Better balance between size and reliability.


πŸ“Š Before vs After: What Changed?

Aspect Before After
πŸ“¦ Image Size ~1.5 GB ~200 MB
βš™οΈ Build Strategy Single-stage Multi-stage
πŸ“ Base Image node:18-alpine node:18-slim
🚫 .dockerignore ❌ None βœ… Included to skip unneeded files
πŸ” Copied Files Everything (including node_modules) Only build/ output copied
πŸš€ Performance Slow build + large deploy Faster build + minimal production image

🎁 Conclusion

If you apply the same strategies, you’ll get:

  • βœ… Smaller Docker Images β†’ Faster pulls/pushes, lower storage cost
  • ⚑ Faster Builds β†’ Especially in CI/CD pipelines
  • πŸ”’ Better Security β†’ No unnecessary source code or secrets inside image
  • 🌍 Portable & Lightweight Images β†’ Ideal for microservices, serverless, and edge deployments

πŸ”— Reference

All the code is live here on my GitHub:
πŸ‘‰ mrzaizai2k/Portfolio

Feel free to clone it, star it ⭐, or ask me anything.


Thanks for reading!
If this helped you, share it with a friend who might still be shipping 1GB containers πŸ˜„

Top comments (1)

Collapse
 
mrzaizai2k profile image
Mai Chi Bao

β€œFrom 1.5GB to 200MB? That’s massive. Just tried this on my project β€” game changer πŸš€β€