Blogchevron_rightserverchevron_rightDocker Multi-Stage Builds: The Complete Guide

Docker Multi-Stage Builds: The Complete Guide

S
Serversium
calendar_today3 Temmuz 2026
schedule5 dk okuma
Docker Multi-Stage Builds: The Complete Guide

What Are Multi-Stage Builds in Docker?

Multi-stage builds are a Docker feature that allows you to use multiple FROM statements in a single Dockerfile. This technique lets you compile your application in one stage and then copy only the necessary artifacts to a final, minimal image. According to a 2023 survey by Docker, organizations using multi-stage builds report image size reductions of up to 90% compared to traditional single-stage builds.

The core problem multi-stage builds solve is bloat. Traditional Dockerfiles often include build tools, dependencies, and compilation artifacts that are unnecessary in production. Multi-stage builds separate the build environment from the runtime environment, ensuring your final image contains only what your application needs to run.

Why Image Size Matters in Docker Projects

Large Docker images impact your development workflow and infrastructure costs in several ways. Here are the key reasons to reduce Docker image sizes:

  • Faster deployments: Smaller images transfer quicker over networks, reducing deployment times significantly
  • Reduced storage costs: Cloud providers charge for container registry storage; smaller images mean lower bills
  • Improved security: Fewer layers and packages mean a smaller attack surface for vulnerabilities
  • Quicker scaling: Orchestration platforms like Kubernetes spawn new pods faster with compact images

Research indicates that the average enterprise Docker image contains approximately 400MB of unnecessary data, according to industry benchmarks.

How Multi-Stage Builds Work

A multi-stage Dockerfile uses multiple FROM instructions, each creating a new build stage. You can name stages using the AS keyword, then reference them when copying artifacts. Here's the basic syntax:

# Stage 1: Build
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# Stage 2: Production
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
CMD ["node", "dist/index.js"]

The COPY --from=builder instruction copies only the necessary files from the builder stage, excluding build tools and intermediate files.

Step-by-Step: Creating an Optimized Dockerfile

Step 1: Choose a Base Image

Select a minimal base image for your final stage. Alpine-based images are popular because they weigh approximately 5MB compared to 900MB+ for standard images. For Node.js, use node:18-alpine. For Python, consider python:3.11-slim.

Step 2: Install Dependencies Separately

Copy only dependency files first, then install them, before copying source code. This leverages Docker's layer caching:

COPY package*.json ./
RUN npm ci --only=production

Step 3: Copy Build Artifacts Only

Use the --from flag to copy compiled artifacts from the builder stage:

COPY --from=builder /app/build ./build
COPY --from=builder /app/public ./public

Step 4: Remove Unnecessary Files

Clean up temporary files, documentation, and development dependencies in the builder stage before copying:

RUN rm -rf /app/src/tests /app/README.md

Comparison: Single-Stage vs Multi-Stage Build

Aspect Single-Stage Build Multi-Stage Build
Final Image Size ~800MB - 1.2GB ~80MB - 150MB
Build Time Baseline +10-20% (negligible)
Security Surface High (includes build tools) Low (production deps only)
Layer Count 15-25 layers 8-12 layers
Maintainability Simple but bloated Slightly more complex

Best Practices for Docker Image Optimization

Follow these industry-recommended practices to achieve maximum image size reduction:

  1. Use minimal base images: Alpine, Slim, or Distroless images reduce base footprint dramatically
  2. Run as non-root user: Create a user in your Dockerfile for security
  3. Combine RUN commands: Reduce layers by chaining commands with &&
  4. Use .dockerignore: Exclude files like node_modules, .git, and tests from build context
  5. Order instructions logically: Place less frequently changed commands first to leverage caching

According to Docker best practices, combining RUN commands can reduce layer count by up to 40%.

Real-World Example: React Application

Here's a complete multi-stage Dockerfile for a React application using Create React App:

# Stage 1: Build
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Stage 2: Serve with Nginx
FROM nginx:alpine
COPY --from=builder /app/build /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

This approach produces an image under 50MB compared to 1GB+ for a traditional Node.js-only image.

Advanced Optimization Techniques

Using Distroless Images

Google's distroless images contain only your application and its runtime dependencies. They have no shell, package manager, or debugging tools, making them extremely secure and minimal.

FROM gcr.io/distroless/nodejs:18
COPY --from=builder /app/dist /app
COPY --from=builder /app/node_modules /app/node_modules
CMD ["dist/index.js"]

Buildkit Caching

Enable Docker BuildKit for faster builds and better caching:

DOCKER_BUILDKIT=1 docker build -t myapp .

Scratch Base Image

For compiled languages like Go, use the scratch base—a completely empty image:

FROM golang:1.21 AS builder
WORKDIR /app
COPY . .
RUN CGO_ENABLED=0 go build -o main .

FROM scratch
COPY --from=builder /app/main /main
ENTRYPOINT ["/main"]

This creates a binary-only image typically under 20MB.

Common Mistakes to Avoid

When implementing multi-stage builds, watch out for these pitfalls:

  • Copying too much: Always specify exact paths rather than copying entire directories
  • Ignoring .dockerignore: This file prevents unnecessary files from bloating your build context
  • Not using alpine images: Standard OS images include many unnecessary utilities
  • Forgetting production dependencies: Ensure production-only npm ci or pip install --no-deps

Conclusion: Start Optimizing Your Docker Images Today

Multi-stage builds are essential for creating efficient, secure, and cost-effective Docker images. By separating your build environment from your runtime environment, you can achieve 70-90% reduction in image size while improving security and deployment speeds.

Start by refactoring one Dockerfile in your project using the techniques outlined in this guide. The benefits—in reduced costs, faster deployments, and improved security—will be immediately noticeable across your development pipeline.

For more guidance on optimizing your infrastructure, explore our comprehensive Docker tutorials and technical documentation. Our support team is ready to help you implement best practices for your containerized applications.

library_booksBenzer İçerikler

cPanel vs Plesk: Complete Guide to Server Panel Extensions
server
calendar_today17 Haziran 2026
schedule5 dk

cPanel vs Plesk: Complete Guide to Server Panel Extensions

Explore the comprehensive guide to cPanel and Plesk extensions. Learn how to enhance your server management panel with security tools, automation, and performance optimization.

S
Serversiumarrow_forward
What Is a Memory Leak on a Server? Detection & Fix Guide
server
calendar_today17 Haziran 2026
schedule5 dk

What Is a Memory Leak on a Server? Detection & Fix Guide

A comprehensive guide to understanding, detecting, and fixing memory leaks on servers. Includes step-by-step methods, tools comparison, and prevention best practices.

S
Serversiumarrow_forward
PHP Version Migration Guide: Upgrade to PHP 8.3 in 2024
server
calendar_today20 Haziran 2026
schedule5 dk

PHP Version Migration Guide: Upgrade to PHP 8.3 in 2024

A comprehensive guide covering PHP version migrations, including a step-by-step upgrade process to PHP 8.3, performance benchmarks, security improvements, and best practices for server administrators.

S
Serversiumarrow_forward