How I Reduced My Docker Image Size by 97% with a Multi-Stage Dockerfile


When I first built my React application, the Docker image was a whopping 1.92 GB. That’s overkill for production — slower builds, longer deployments, and unnecessary storage costs. After some optimization, I brought it down to just 64 MB.
Here’s how we can do it.
First let’s understand Why Image Size Matters
Faster Deployments – Smaller images push/pull much quicker.
Lower Costs – Uses less storage space.
Better Security – Fewer unused packages = smaller attack surface.
Ways to Reduce Docker Image Size
1️⃣ Modify Dependencies
In package.json
, separate dev and prod dependencies.
Dev Environment → Install dev + prod dependencies.
Prod Environment → Install only prod dependencies.
How will docker know, only to run prod dependencies?
2️⃣ Use Smaller Base Images
First, let’s try using the default Node.js image and then compare it with the Alpine and Slim variants.
If we run Docker with the Node.js image
Size of image is 1.92GB
Now try with the alpine and slim images
Alpine → Very small, has package manager (
apk
).Slim → Slightly larger but more compatible.
Distroless → Minimal runtime, but lacks package managers.
With slim base image
With alpine and slim base image the size reduces from 1.92GB to 959MB
3️⃣ Multi-Stage Docker Build (Game-Changer)
The idea:
Stage 1 → Build the app.
Stage 2 → Copy only the build artifacts into a minimal image.
Example for a React app served with Nginx:
docker build -t app:multistage-serve .
The final image size reduces to 64MB
Deploy to Web Servers
Instead of using node:alpine
(≈ 240 MB), serve static assets via nginx:alpine
(≈ 43 MB).
That’s how we got the final image down to 64 MB.
Results
Approach | Image Size |
Single-stage build | 1.92 GB |
Slim base image | ~950 MB |
Alpine base image | ~1.02 GB |
Multi-stage + nginx:alpine | 64 MB |
Subscribe to my newsletter
Read articles from Abhishek Mishra directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
