Giới thiệu

Dockerfile là nền tảng để xây dựng image, nhưng nếu không tối ưu sẽ dẫn đến image quá lớn, tốn băng thông và thời gian khởi động. Multi‑stage build là kỹ thuật cho phép tách các bước biên dịch và runtime vào các stage riêng, chỉ giữ lại những thành phần cần thiết cho môi trường production.

Tại sao nên sử dụng multi‑stage build

So với việc tạo một Dockerfile duy nhất, multi‑stage giúp:

  • Loại bỏ các công cụ biên dịch, thư viện phát triển không cần thiết.
  • Giảm kích thước layer cuối cùng, thường giảm 50‑80%.
  • Dễ bảo trì vì mỗi stage có mục tiêu rõ ràng.

Các bước tối ưu Dockerfile đa giai đoạn

1. Xác định stage build

Đầu tiên tạo một stage builder dùng image có sẵn như node:18‑alpine hoặc golang:1.22 để biên dịch mã nguồn.

2. Tách stage runtime

Sau khi biên dịch xong, chuyển sang một stage nhẹ hơn (thường là alpine hoặc scratch) và chỉ COPY các file đã biên dịch.

3. Sử dụng .dockerignore hợp lý

Loại bỏ các thư mục không cần thiết (ví dụ node_modules, test, .git) để giảm thời gian copy.

4. Tối ưu layer

Ghép các lệnh RUN liên tiếp bằng && và xóa cache ngay trong cùng một layer để tránh tạo layer dư thừa.

Ví dụ Dockerfile đa giai đoạn cho ứng dụng Node.js

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

# Stage 2: Runtime
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package*.json ./
RUN npm install --production --ignore-scripts
EXPOSE 3000
CMD ["node", "dist/index.js"]

Trong ví dụ trên, builder chứa toàn bộ môi trường phát triển, còn stage cuối chỉ giữ dist và các dependency production.

Kiểm tra kích thước image

Sau khi build, sử dụng lệnh docker images để so sánh kích thước. Đối với cùng một ứng dụng, image đa giai đoạn thường nhỏ hơn 150 MB, trong khi image đơn stage có thể lên tới 400 MB.

docker build -t myapp:latest .
docker images myapp:latest

Lưu ý khi triển khai thực tế

  • Đảm bảo mọi biến môi trường cần thiết được truyền ở stage runtime, không để lại thông tin nhạy cảm trong stage build.
  • Nếu cần sử dụng scratch, hãy chắc chắn rằng binary đã được biên dịch tĩnh (static).
  • Sử dụng docker-compose.yml để quản lý nhiều container, nhưng vẫn giữ mỗi container dựa trên image đã tối ưu.

Kết luận

Áp dụng multi‑stage build là cách hiệu quả nhất để giảm kích thước Docker image, cải thiện thời gian triển khai và bảo mật. Nếu bạn muốn học sâu hơn về cách cấu hình Dockerfile, Docker Compose và các chiến lược tối ưu, Tham khảo khóa học "Làm chủ Docker từ cơ bản đến nâng cao" tại đây.