Docker Multi-Stage Builds
Multi-stage builds allow you to create smaller, more secure Docker images by separating build and runtime environments.
The Problem
Traditional Dockerfile includes build tools in the final image:
FROM node:18
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
CMD ["node", "dist/index.js"]
Result: ~1GB image with unnecessary build dependencies!
The Solution: Multi-Stage Build
# Build stage
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Production stage
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"]
Result: ~200MB image with only runtime dependencies!
Benefits
- Smaller images: 5-10x size reduction
- Faster deployments: Less data to transfer
- Better security: Fewer attack surfaces
- Cleaner production: No build tools in production
For Laravel Applications
# Composer dependencies
FROM composer:2 AS composer
WORKDIR /app
COPY composer.* ./
RUN composer install --no-dev --optimize-autoloader
# Node assets
FROM node:18 AS node
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Production
FROM php:8.3-fpm-alpine
WORKDIR /var/www
COPY --from=composer /app/vendor ./vendor
COPY --from=node /app/public/build ./public/build
COPY . .
Flow Diagram
Multi-stage builds are a Docker best practice that every developer should use!
Thử thách
Luyện tập ngay điều vừa học. Viết lời giải, mở gợi ý nếu bí.
Đề bài
This single-stage Dockerfile ships the full Node toolchain and dev dependencies in the final image — large and less secure. Rewrite it as a multi-stage build: install and build in a `builder` stage, then copy only the built output and production dependencies into a slim runtime image.
Code khởi tạo
FROM node:20
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
CMD ["node", "dist/server.js"]
Lời giải của bạn
# --- build stage ---
FROM node:20 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# --- runtime stage (slim) ---
FROM node:20-slim
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY --from=builder /app/dist ./dist
CMD ["node", "dist/server.js"]

