Multi-Stage Builds

Use Docker multi-stage builds to compile applications in one stage and ship a smaller, cleaner runtime image.

Last reviewed: June 2026

·Docker Engine 24+Docker Desktop 4+Docker Compose v2
✅
Quick Understanding: A multi-stage build uses multiple `FROM` stages. Build tools and source files stay in the builder stage, while only the final compiled artifact is copied into the runtime stage.

🔍 What Is It?

Multi-stage builds separate build-time dependencies from runtime dependencies.

The first stage may include compilers, package managers, test tooling, and source code. The final stage contains only what is needed to run the app.

This creates smaller, safer, faster-to-pull images.

🎯 Why Do We Need It?

Without multi-stage builds, production images often contain:

  • →Source code that is not needed at runtime
  • →Compilers and build tools
  • →Package manager caches
  • →Test frameworks
  • →Dev dependencies

That increases image size and security exposure.

🏗️ What Happens in Real Projects?

Multi-stage builds are standard for Java, Go, Node, frontend static sites, and many compiled services.

A React app might build static assets in a Node stage and serve only the dist folder from Nginx. A Spring Boot app might build with Maven in one stage and run the final jar on a JRE image.

⚙️ How It Works

Each FROM starts a new stage. You can name stages with AS.

The final stage uses COPY --from=<stage> to pull selected files from an earlier stage.

Only the final stage becomes the image unless you explicitly target another stage.

💻 Example

Build React, Serve with Nginx — The Node build toolchain stays out of the production runtime image.

dockerfile
FROM node:22-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

🤔 Common Confusions

❓ Do all stages ship to production?

No. By default, only the final stage becomes the resulting image.

❓ Can I stop at an earlier stage?

Yes. `docker build --target build` can build a specific stage for debugging or CI steps.

❓ Is multi-stage only for compiled languages?

No. It is useful whenever build-time tools are not needed in the runtime image.

🚨 Common Production Issues

**Artifacts missing** - final stage copies the wrong output path and the app fails at startup.

**Runtime dependencies omitted** - native libraries required by the built artifact are absent from the final image.

**Cache inefficiency** - build stage copies all source before installing dependencies.

**Secrets in builder stage** - build secrets are handled carelessly and may leak into layers or logs.

✅ Best Practices

Name build stages for readability

Copy only required artifacts into the final image

Keep dependency installation cache-friendly

Use BuildKit secrets for private package access

Test the final image, not only the build stage

Choose a runtime base image that matches application needs

🏛️ Architect's Note

Senior Architect's Perspective

Multi-stage builds are one of the easiest ways to improve Docker maturity. They reduce image size, attack surface, and deployment time without changing application code.

For enterprise standards, make multi-stage builds the default for compiled or bundled applications.

💬 Frequently Asked Questions

Can multi-stage builds improve security?

Yes. They keep build tools and unnecessary files out of the final runtime image, reducing attack surface.

Can I have more than two stages?

Yes. Teams often use separate stages for dependencies, testing, building, and runtime.

Does the final image know about previous stages?

Only through files explicitly copied from those stages.

🎯 Key Takeaways

1Multi-stage builds separate build and runtime concerns
2Only the final stage becomes the output image by default
3They reduce image size and attack surface
4Use `COPY --from` to transfer selected artifacts
5Always test the final runtime image

🎯 Practice this topic in interviews

↗ Where this topic fits

Sources

Sources / References

Use these Docker references to verify the concept in official docs and continue into the most relevant SplashRide pages.