Multi-stage build và non-root
Tách builder khỏi runtime và giảm attack surface.
Nắm bản chất
Multi-stage build cho phép compile/install trong một stage rồi chỉ copy artifact cần thiết sang runtime stage. Điều này đặc biệt hữu ích với Go, Rust, Node/TypeScript, Java và frontend static sites.
Runtime image nhỏ hơn có thể giảm dung lượng truyền và số thành phần có thể bị ảnh hưởng bởi vulnerabilities. Nhưng base image nhỏ không tự bảo đảm an toàn: phải kiểm tra updates, CA certificates, timezone libraries và runtime dependencies còn cần.
Luồng hoạt động
Hãy tự giải thích mỗi mũi tên: dữ liệu, quyền hoặc tín hiệu nào được truyền qua bước này?
Lệnh & cấu hình mẫu
FROM golang:1.25-alpine AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /out/server ./cmd/server
FROM alpine:3.22
RUN adduser -D -u 10001 app
USER 10001
COPY --from=build /out/server /usr/local/bin/server
ENTRYPOINT ["/usr/local/bin/server"]
Lệnh có placeholder hoặc phụ thuộc môi trường thì cần thay thông tin thực tế, kiểm tra quyền và chỉ thực hiện trên tài nguyên được phép.
Bài tập 10–20 phút
Nếu bạn dùng Go, build cùng ứng dụng theo single-stage rồi multi-stage để so sánh số layers và image size. Nếu chưa dùng Go, áp dụng nguyên tắc cho builder/frontend của riêng bạn.
Lỗi dễ mắc
Ví dụ version tags là mốc học tập; production phải kiểm tra phiên bản/toolchain đang được hỗ trợ và pin digest khi phù hợp. Alpine có musl khác glibc, có thể ảnh hưởng native binaries.
Tự kiểm tra
Tại sao builder stage không nên luôn tồn tại trong runtime image?Xem đáp án ↗
Compiler, package managers và build credentials thường không cần ở runtime; loại bỏ chúng giảm size và attack surface.
Học thêm qua lab
Bài học nền tảng có thể thực hiện trực tiếp bằng các lệnh trên; bảng tra cứu nhanh giúp ôn tập.
→ Mở bảng lệnh tra cứu nhanhĐối chiếu tài liệu gốc
Cú pháp và khả năng hỗ trợ có thể thay đổi theo phiên bản. Trước khi dùng Production, hãy kiểm tra tài liệu tương ứng.
Mở tài liệu chính thức ↗