π³ Docker Multi-Stage Build - Complete Documentation
π Table of Contents
- π― What is Docker Multi-Stage Build?
- π Why Use Multi-Stage Builds?
- ποΈ How Multi-Stage Builds Work
- π¦ Step-by-Step Tutorial
- π Multi-Stage Build Workflow
- π Architecture Diagrams
- π οΈ Commands and Best Practices
- β‘ Performance Comparison
- π§ Debugging and Troubleshooting
- β¨ Best Practices
π― What is Docker Multi-Stage Build?
Docker Multi-Stage Build is a powerful feature that allows you to use multiple FROM
statements in a single Dockerfile[1]. Each FROM
instruction creates a new stage in the build process, enabling you to optimize image size and improve security by separating build dependencies from runtime requirements[2].
π€ Key Concepts
- ποΈ Multiple Stages: Each stage has its own base image and purpose
- π¦ Selective Copying: Copy only necessary artifacts between stages
- ποΈ Artifact Exclusion: Build tools and dependencies are left behind
- π― Production-Ready: Final image contains only runtime requirements
π Why Use Multi-Stage Builds?
Multi-stage builds solve several critical problems in containerized application development[3]:
π― Benefit | π Description | π‘ Impact |
---|---|---|
π Smaller Image Size | Excludes build tools and dependencies from final image | π Faster deployments |
π Enhanced Security | Reduces attack surface by removing unnecessary components | π‘οΈ Lower vulnerability risk |
β‘ Better Performance | Lighter images load and start faster | π Improved runtime speed |
π§Ή Cleaner Workflow | Single Dockerfile for entire build process | π οΈ Simplified maintenance |
π° Cost Optimization | Reduced storage and bandwidth usage | π΅ Lower infrastructure costs |
ποΈ How Multi-Stage Builds Work
π Single-Stage vs Multi-Stage Comparison
graph TB subgraph "β Single-Stage Build Problems" SINGLE[π¦ Single Stage] SINGLE --> BUILD_TOOLS[π§ Build Tools] SINGLE --> SOURCE[π Source Code] SINGLE --> DEPS[π All Dependencies] SINGLE --> ARTIFACTS[β‘ Build Artifacts] SINGLE --> FINAL1[π¦ Final Image: 200MB+] end subgraph "β
Multi-Stage Build Solution" STAGE1[ποΈ Build Stage] STAGE2[π Runtime Stage] STAGE1 --> BUILD_TOOLS2[π§ Build Tools] STAGE1 --> SOURCE2[π Source Code] STAGE1 --> BUILD_DEPS[π Build Dependencies] STAGE1 --> COMPILE[βοΈ Compile/Build] STAGE2 --> RUNTIME_BASE[π Runtime Base Image] STAGE2 --> COPY_ARTIFACTS[π Copy Build Artifacts] STAGE2 --> FINAL2[π¦ Final Image: 50MB] COMPILE -.->|Copy Only Artifacts| COPY_ARTIFACTS end
π Build Process Flow
sequenceDiagram participant User as π€ Developer participant Docker as π³ Docker Engine participant Stage1 as ποΈ Build Stage (installer) participant Stage2 as π Runtime Stage (deployer) participant Registry as π¦ Image Registry User->>Docker: docker build -t multistage . Docker->>Stage1: FROM node:18-alpine AS installer Stage1->>Stage1: WORKDIR /app Stage1->>Stage1: COPY package*.json ./ Stage1->>Stage1: RUN npm install Stage1->>Stage1: COPY . . Stage1->>Stage1: RUN npm run build Docker->>Stage2: FROM nginx:latest AS deployer Stage2->>Stage1: COPY --from=installer /app/build /usr/share/nginx/html Docker->>User: π¦ Optimized Image Ready (50MB) User->>Registry: docker push multistage
π¦ Step-by-Step Tutorial
π οΈ Project Setup
1. Clone the Application
git clone cd react-app-docker ls # Check project structure
Project Structure:
react-app-docker/ βββ src/ βββ public/ βββ package.json βββ package-lock.json βββ README.md
π Creating Multi-Stage Dockerfile
2. Create Dockerfile
touch Dockerfile vi Dockerfile
3. Multi-Stage Dockerfile Content
# ποΈ Stage 1: Build Stage (installer) FROM node:18-alpine AS installer WORKDIR /app # Copy package files for dependency installation COPY package*.json ./ # Install all dependencies (including devDependencies) RUN npm install # Copy source code COPY . . # Build the application RUN npm run build # π Stage 2: Runtime Stage (deployer) FROM nginx:latest AS deployer # Copy only build artifacts from previous stage COPY --from=installer /app/build /usr/share/nginx/html # Nginx will serve the static files EXPOSE 80
π§ Build Process
4. Build the Multi-Stage Image
docker build -t multistage .
π Build Output Analysis
graph LR subgraph "ποΈ Build Stage Process" A[π package.json] --> B[π¦ npm install] C[π Source Code] --> B B --> D[βοΈ npm run build] D --> E[π /app/build] end subgraph "π Runtime Stage Process" F[π nginx:latest] --> G[π Copy build artifacts] E -.->|COPY --from=installer| G G --> H[π― Final Image] end style E fill:#90EE90 style H fill:#87CEEB
π Multi-Stage Build Workflow
π― Complete Workflow Diagram
flowchart TD START([π Start Build Process]) --> STAGE1{ποΈ Build Stage} STAGE1 --> NODE[π¦ FROM node:18-alpine AS installer] NODE --> WORKDIR[π WORKDIR /app] WORKDIR --> COPY_PKG[π COPY package*.json ./] COPY_PKG --> NPM_INSTALL[β¬οΈ RUN npm install] NPM_INSTALL --> COPY_SRC[π COPY . .] COPY_SRC --> NPM_BUILD[βοΈ RUN npm run build] NPM_BUILD --> STAGE2{π Runtime Stage} STAGE2 --> NGINX[π FROM nginx:latest AS deployer] NGINX --> COPY_BUILD[π COPY --from=installer /app/build /usr/share/nginx/html] COPY_BUILD --> FINAL[β¨ Optimized Final Image] FINAL --> SIZE_CHECK{π Size Check} SIZE_CHECK -->|Before: 200MB+| BEFORE[β Single Stage: Bloated] SIZE_CHECK -->|After: ~50MB| AFTER[β
Multi-Stage: Optimized] style STAGE1 fill:#FFE4B5 style STAGE2 fill:#E0FFFF style FINAL fill:#90EE90 style AFTER fill:#98FB98
π Stage Dependency Graph
graph TB subgraph "π¦ Base Images" NODE18[π’ node:18-alpine] NGINX[π΅ nginx:latest] end subgraph "ποΈ Build Stage (installer)" INSTALLER[installer stage] BUILD_DEPS[π Build Dependencies] SOURCE_CODE[π Source Code] BUILD_ARTIFACTS[β‘ Build Artifacts] NODE18 --> INSTALLER INSTALLER --> BUILD_DEPS INSTALLER --> SOURCE_CODE BUILD_DEPS --> BUILD_ARTIFACTS SOURCE_CODE --> BUILD_ARTIFACTS end subgraph "π Runtime Stage (deployer)" DEPLOYER[deployer stage] STATIC_FILES[π Static Files Only] NGINX --> DEPLOYER BUILD_ARTIFACTS -.->|COPY --from=installer| DEPLOYER DEPLOYER --> STATIC_FILES end subgraph "ποΈ Excluded from Final Image" EXCLUDED[β node_modulesβ Source codeβ Build toolsβ Dev dependencies] end style BUILD_ARTIFACTS fill:#90EE90 style STATIC_FILES fill:#87CEEB style EXCLUDED fill:#FFB6C1
π οΈ Commands and Best Practices
π§ Essential Docker Commands
Build Commands
# Build multi-stage image docker build -t multistage . # Build with specific target stage docker build --target installer -t build-stage . # Build with build arguments docker build --build-arg NODE_VERSION=18 -t multistage .
Image Management
# List all images docker images # Remove specific image docker image rm multistage # Remove dangling images docker image prune # Check image size docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
Container Operations
# Run container docker run -d -p 3000:80 --name app-container multistage # Check running containers docker ps # View container logs docker logs # Execute commands in container docker exec -it /bin/sh
π Debugging and Inspection Commands
# Inspect container configuration docker inspect # Check container filesystem docker exec -it ls -la /usr/share/nginx/html # Monitor container resource usage docker stats # View container port mappings docker port
π Performance Comparison
π Size Comparison
graph LR subgraph "π Image Size Comparison" SINGLE[β Single-Stage200MB+] MULTI[β
Multi-Stage~50MB] SINGLE --> REDUCTION[75% Size Reduction] REDUCTION --> MULTI end subgraph "β‘ Performance Impact" FASTER[π 3x Faster Pull] SECURE[π Lower Attack Surface] COST[π° Reduced Storage Cost] end MULTI --> FASTER MULTI --> SECURE MULTI --> COST style SINGLE fill:#FFB6C1 style MULTI fill:#90EE90 style REDUCTION fill:#FFD700
π Benefits Breakdown
π Metric | π΄ Single-Stage | π’ Multi-Stage | π Improvement |
---|---|---|---|
π¦ Image Size | 200MB+ | ~50MB | 75% reduction |
β¬οΈ Pull Time | 30 seconds | 10 seconds | 3x faster |
π Startup Time | 15 seconds | 8 seconds | 2x faster |
π Security Vulnerabilities | High | Low | 60% fewer |
πΎ Storage Cost | High | Low | 75% savings |
π§ Debugging and Troubleshooting
π Container Investigation Commands
# Check container logs docker logs # Access container shell docker exec -it /bin/sh # Inspect container details docker inspect
π΅οΈ Inside Container Exploration
graph TB CONTAINER[π³ Running Container] subgraph "π Container Filesystem" ROOT[/ (root directory)] USR[/usr] SHARE[/usr/share] NGINX[/usr/share/nginx] HTML[/usr/share/nginx/html] FILES[π Static Files] ROOT --> USR USR --> SHARE SHARE --> NGINX NGINX --> HTML HTML --> FILES end subgraph "π Inspection Commands" LS[ls -la] CAT[cat index.html] PS[ps aux] TOP[top] end CONTAINER --> ROOT FILES --> LS FILES --> CAT style FILES fill:#90EE90 style HTML fill:#87CEEB
π¨ Common Issues and Solutions
β Problem | π Symptom | β Solution |
---|---|---|
Build fails | unknown instruction WORKDIR | Check Dockerfile syntax |
Large image size | Image still 200MB+ | Verify multi-stage is working |
Container won't start | Exit code 125 | Check port conflicts |
Files not found | 404 errors | Verify COPY paths |
Permission issues | Access denied | Use non-root user |
β¨ Best Practices
π― Multi-Stage Build Best Practices
1. π·οΈ Use Named Stages
# β
Good: Named stages FROM node:18-alpine AS installer FROM nginx:latest AS deployer # β Bad: Unnamed stages FROM node:18-alpine FROM nginx:latest
2. π¦ Choose Optimal Base Images
# β
Good: Lightweight base images FROM node:18-alpine AS installer # Small Alpine-based FROM nginx:alpine AS deployer # Lightweight nginx # β Bad: Heavy base images FROM node:18 AS installer # Ubuntu-based (larger) FROM nginx:latest AS deployer # Full nginx image
3. π― Copy Only What's Needed
# β
Good: Selective copying COPY --from=installer /app/build /usr/share/nginx/html # β Bad: Copying everything COPY --from=installer /app /usr/share/nginx/html
4. π Optimize Layer Caching
# β
Good: Copy package files first COPY package*.json ./ RUN npm install COPY . . # β Bad: Copy everything first COPY . . RUN npm install
π Security Best Practices
5. π€ Use Non-Root User
# β
Good: Non-root user FROM nginx:alpine AS deployer RUN addgroup -g 1001 -S nodejs RUN adduser -S nextjs -u 1001 USER nextjs # β Bad: Running as root (default) FROM nginx:alpine AS deployer # No user specified - runs as root
6. ποΈ Remove Unnecessary Packages
# β
Good: Clean up after installation RUN apt-get update && apt-get install -y \ package1 \ package2 \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* # β Bad: Leave package cache RUN apt-get update && apt-get install -y package1 package2
π Performance Best Practices
7. π― Use Specific Targets
# Build only specific stage for testing docker build --target installer -t build-stage . # Build final production image docker build -t production-app .
8. π¦ Multi-Architecture Support
# Support multiple architectures FROM --platform=$BUILDPLATFORM node:18-alpine AS installer # Build process... FROM --platform=$TARGETPLATFORM nginx:alpine AS deployer # Runtime setup...
π Advanced Multi-Stage Patterns
9. π§ͺ Testing Stage
# Build stage FROM node:18-alpine AS installer WORKDIR /app COPY package*.json ./ RUN npm install COPY . . RUN npm run build # Test stage FROM installer AS tester RUN npm test # Production stage FROM nginx:alpine AS deployer COPY --from=installer /app/build /usr/share/nginx/html
10. π Parallel Builds
# Base dependencies FROM node:18-alpine AS base WORKDIR /app COPY package*.json ./ RUN npm install # Frontend build FROM base AS frontend COPY frontend/ ./ RUN npm run build:frontend # Backend build FROM base AS backend COPY backend/ ./ RUN npm run build:backend # Final stage FROM nginx:alpine AS final COPY --from=frontend /app/dist /usr/share/nginx/html COPY --from=backend /app/build /app/api
π Additional Best Practices
mindmap root((π― Multi-StageBest Practices)) ποΈ Build Optimization π¦ Use Alpine images π― Named stages π Layer caching ποΈ .dockerignore file π Security π€ Non-root user π§Ή Clean package cache π Minimal attack surface π« No secrets in layers β‘ Performance π Parallel builds π Smaller final image π Faster deployments πΎ Reduced storage π οΈ Maintenance π Clear documentation π·οΈ Consistent naming π§ͺ Testing stages π CI/CD integration
π Summary
Docker Multi-Stage Builds are a game-changing feature that revolutionizes container image optimization[1][2]. By separating build and runtime environments, you can achieve:
π Key Achievements
- π 75% smaller images - From 200MB+ to ~50MB
- π Enhanced security - Reduced attack surface
- β‘ Faster deployments - 3x faster pull times
- π° Cost savings - Lower storage and bandwidth costs
- π§Ή Cleaner workflow - Single Dockerfile for entire process
π Implementation Steps
- ποΈ Design stages - Separate build and runtime concerns
- π¦ Choose base images - Use lightweight Alpine variants
- π― Copy selectively - Only production artifacts
- π Apply security - Non-root users, clean packages
- π Monitor results - Measure size and performance improvements
Multi-stage builds represent a fundamental shift from monolithic container images to optimized, production-ready deployments. They embody the principle of "build fat, ship thin" - using all necessary tools during build time while delivering minimal, secure runtime images[3].
Start implementing multi-stage builds in your projects today to unlock significant performance gains and security improvements in your containerized applications! π
[1] https://docs.docker.com/build/building/multi-stage/
[2] https://docs.docker.com/get-started/docker-concepts/building-images/multi-stage-builds/
[3] https://docs.docker.com/build/building/best-practices/
[4] https://docs.docker.com/guides/cpp/multistage/
[5] https://dev.to/raunakgurud09/mastering-docker-multistage-builds-1e0m
[6] https://dev.to/abhay_yt_52a8e72b213be229/streamline-your-docker-images-with-multi-stage-builds-340c
[7] https://depot.dev/blog/docker-multi-stage-builds
[8] https://dev.to/citrux-digital/understanding-docker-multistage-builds-3fm7
[9] https://labs.iximiuz.com/tutorials/docker-multi-stage-builds
[10] https://dev.to/kalkwst/multi-stage-dockerfiles-3e90
[11] https://ruan.dev/blog/2022/07/31/docker-multistage-builds-for-hugo
[12] https://www.cherryservers.com/blog/docker-multistage-build
[13] https://github.com/patrickhoefler/dockerfilegraph
[14] https://docs.docker.com/build/building/multi-platform/
[15] https://overcast.blog/building-efficient-multi-stage-dockerfiles-for-production-055f34c4baed
[16] https://learn.microsoft.com/en-us/dotnet/architecture/microservices/docker-application-development-process/docker-app-development-workflow
[17] https://docs.docker.com/get-started/docker-concepts/building-images/writing-a-dockerfile/
[18] https://earthly.dev/blog/docker-multistage/
[19] https://blog.devgenius.io/docker-multi-stage-build-in-detail-3d7da2948797?gi=265baab36942
[20] https://www.youtube.com/watch?v=ajetvJmBvFo
Top comments (0)