
Bài 1: Cài Docker Engine trên Ubuntu và Rocky Linux 9
Cài Docker Engine từ kho phù hợp, kiểm tra phiên bản và quyền truy cập; phân biệt lưu trữ containerd mới với overlay2 trên máy nâng cấp.

Tách builder khỏi runtime, kiểm tra tương thích libc và native module; giảm thành phần không cần thiết mà không cam kết tỷ lệ dung lượng chưa đo.
Đối chiếu ngày 24/10/2026. Các nguồn ở cuối bài dùng để kiểm tra phiên bản và giới hạn. Ví dụ phải điều chỉnh theo hệ điều hành và ứng dụng; không phải báo cáo thử nghiệm trên mọi nền tảng.
Trong quy trình đóng gói truyền thống, một Docker Image thường chứa đầy đủ:
Kích thước image phụ thuộc runtime, dependency và artifact. Đo image hiện tại trước khi tối ưu; image nhỏ không đồng nghĩa ứng dụng đã an toàn.

Multi-stage Builds cho phép bạn khai báo nhiều chỉ thị FROM trong cùng một file Dockerfile:
COPY --from=builder.Chỉ artifact được COPY sang stage cuối xuất hiện trong filesystem image cuối. Builder cache và stage trung gian vẫn cần chính sách bảo vệ; sao chép nhầm secret hoặc source vẫn có thể đưa chúng vào runtime.
Dưới đây là một Dockerfile 3 giai đoạn tối ưu cho ứng dụng TypeScript:
# ==========================================
# GIAI ĐOẠN 1: Cài đặt toàn bộ dependencies
# ==========================================
FROM node:24-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
# ==========================================
# GIAI ĐOẠN 2: Biên dịch TypeScript sang JavaScript
# ==========================================
FROM node:24-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
# Loại bỏ devDependencies chỉ giữ lại production dependencies
RUN npm prune --omit=dev
# ==========================================
# GIAI ĐOẠN 3: Runtime mỏng nhẹ chuẩn Production
# ==========================================
FROM node:24-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
# Tạo user không có quyền root
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
# Chỉ copy bundle đã build và node_modules production sạch
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./package.json
USER appuser
EXPOSE 3000
CMD ["node", "dist/main.js"]
Đây là cấu hình minh họa, không có benchmark dung lượng cho ứng dụng của bạn. So sánh docker image inspect, docker history, rồi kiểm thử chức năng và tải trước/sau.
Với các ngôn ngữ biên dịch thành mã máy nhị phân tĩnh (Static Binary) như Golang hoặc Rust, bạn thậm chí có thể sử dụng base image rỗng scratch:
# Stage 1: Compiler
FROM golang:1.27-alpine AS builder
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
# Bien dich tinh khong phu thuoc libc cua he dieu hanh
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -o /bin/api-server
# Stage 2: Scratch (Sieu nho gon, chi co file binary)
FROM scratch
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /bin/api-server /api-server
EXPOSE 8080
ENTRYPOINT ["/api-server"]
Dung lượng binary Go và CA bundle thay đổi theo ứng dụng. CGO_ENABLED=0 chỉ phù hợp khi dependency hỗ trợ; scratch còn cần xử lý UID, chứng chỉ và dữ liệu runtime.
Distroless là các image do Google phát triển, chỉ chứa ứng dụng của bạn và các thư viện runtime phụ thuộc tối thiểu (như glibc, libssl), hoàn toàn không có shell (sh, bash), không có package manager và không có các tiện ích hệ điều hành chuẩn.
FROM node:24-trixie-slim AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build && npm prune --omit=dev
FROM gcr.io/distroless/nodejs24-debian13:nonroot
WORKDIR /app
COPY --from=builder --chown=65532:65532 /app/dist ./dist
COPY --from=builder --chown=65532:65532 /app/node_modules ./node_modules
COPY --from=builder --chown=65532:65532 /app/package.json ./package.json
CMD ["dist/main.js"]
Không có shell làm giảm một số tiện ích sẵn có, không ngăn mọi RCE hoặc thoát container. Chạy non-root, giảm capability, cập nhật dependency và kiểm soát quyền host vẫn cần thiết.
Trước khi đưa image lên môi trường sản xuất, bạn nên tích hợp công cụ quét lỗ hổng (Vulnerability Scanner) vào đường ống CI/CD:
# 1. Su dung Docker Scout tich hop san
docker scout cves my-app:production
# 2. Su dung cong cu Trivy ma nguon mo sieu toc
trivy image --severity HIGH,CRITICAL my-app:production
Trivy sẽ rà soát toàn bộ các gói phần mềm trong image và cảnh báo các mã CVE (Common Vulnerabilities and Exposures) nghiêm trọng kèm phiên bản cần nâng cấp để vá lỗi.
USER nonroot (UID khác 0, phù hợp quyền file).--read-only) kết hợp tmpfs cho các thư mục tạm..env khỏi các layer Dockerfile.Ở bài học tiếp theo, chúng ta sẽ chuyển sang khía cạnh quản trị lưu trữ: phân biệt chi tiết giữa Named Volumes, Bind Mounts và Tmpfs.
Ví dụ chọn Node.js 24 còn được hỗ trợ thay Node.js 20 đã EOL. Tag nhánh thay đổi bản vá: ghi nhận digest và scan trước release. Không copy native module build trên Alpine/musl sang distroless Debian/glibc nếu chưa kiểm tra tương thích. Mẫu distroless dùng builder Debian cùng họ với runtime.

Đọc đúng tài liệu theo phiên bản. Địa chỉ, tên và đường dẫn trong ví dụ cần thay theo môi trường. Sơ đồ là khái niệm, không phải screenshot hay benchmark.
Lưu cấu hình và digest cũ, kiểm tra backup phục hồi được, xác nhận endpoint và log sau thay đổi. Rollback phải tính đến dữ liệu đã ghi mới; đổi image không tự phục hồi database.

Cài Docker Engine từ kho phù hợp, kiểm tra phiên bản và quyền truy cập; phân biệt lưu trữ containerd mới với overlay2 trên máy nâng cấp.

Tra trạng thái, đọc log, kiểm tra OOM và giới hạn tài nguyên; hiểu tác động của stop, restart và prune trước khi thao tác trên máy production.

Phân biệt tag và digest, save/load với export; chuẩn bị TLS, xác thực và quy trình garbage collection trước khi vận hành private registry.

Chọn driver theo phạm vi kết nối, dùng DNS mạng tự tạo và kiểm tra published port; phân biệt mạng Docker Swarm với mô hình CNI của Kubernetes.