Your Docker container works.
That's great.
But how large is the image?
A 1.5 GB image may work perfectly, but it's carrying a lot of unnecessary data if your application only needs 200 MB to run.
Large Images Have a Cost
A larger container image can mean:
Longer uploads Longer downloads Slower deployments More storage usage More layers to manage
You don't necessarily notice the difference during local development.
Production makes it more obvious.
Development Dependencies Don't Always Belong in Production
Imagine a Node.js application.
During development, you might need:
Testing tools Linters TypeScript tooling Development servers
Your production container may only need the compiled application and runtime dependencies.
That's where multi-stage Docker builds help.
Build Once, Run Smaller
A common structure looks like:
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./ RUN npm ci
COPY . . RUN npm run build
FROM node:20-alpine AS runner
WORKDIR /app
COPY --from=builder /app/package*.json ./ COPY --from=builder /app/node_modules ./node_modules COPY --from=builder /app/.next ./.next
CMD ["npm", "start"]
The build stage does the heavy work.
The final stage contains only what the application needs to run.
Hostwares recommends multi-stage Docker builds to minimize final image size.
Smaller Doesn't Automatically Mean Better
Don't optimize blindly.
A smaller image is useful only if it still contains everything your application requires.
Test the final container before deploying it.
Look at the Runtime, Not Just the Build
Ask:
What does my application actually need after compilation?
Anything that exists only to build the application may not belong in the final image.
Build big if necessary. Run only what you need.