Docker Multi-stage Build

Đóng gói một Go service từ ~1GB xuống ~10MB. Ba mô phỏng tương tác: so sánh image size, layer caching, và lựa chọn base image.

1. Single-stage vs Multi-stage — vì sao 1GB → 10MB

Image cuối của single-stage chứa nguyên cả toolchain Go (chỉ cần lúc build). Multi-stage chỉ giữ lại binary. Bấm nút để xem layer nào bị bỏ lại ở stage builder.

Image cuối

FROM golang:1.24 (single)

Phân tích

Lưu ý: thêm RUN rm -rf /usr/local/go ở layer sau không giảm size — layer trước vẫn nằm trong image. Cách đúng là không bao giờ cho toolchain vào image cuối → multi-stage.

2. Layer caching — thứ tự COPY quyết định tốc độ

Cache invalidate dây chuyền: một layer đổi → mọi layer dưới rebuild. Chọn thứ tự rồi bấm "Sửa 1 dòng code" để xem layer nào HIT/MISS.

Thời gian build lần này
Tình huống
Bấm một nút ở trên

3. Base image: scratch / distroless / alpine

Stage cuối nên dựa base nào? Trade-off giữa kích thước, khả năng debugattack surface.

scratch

Attack surface (càng ngắn càng an toàn)

Quy luật chung: image càng tối giản (scratch/distroless) thì kẻ tấn công vào được càng không có công cụ (không sh, không curl) để leo thang.