
Bạn đã bao giờ rơi vào cảnh ngồi đợi “dài cổ” nhìn pipeline CI/CD chạy mất cả chục phút chỉ vì bước docker push hoặc docker pull một Image nặng tới hơn 1GB chưa? Hoặc đau đầu hơn khi nhận được cảnh báo hệ thống hết dung lượng lưu trữ (Disk Space) trên server Production?
Trong kỷ nguyên Cloud Native, việc giữ cho Docker Image tinh gọn không chỉ giúp tiết kiệm chi phí lưu trữ, tăng tốc độ deploy mà còn giảm thiểu đáng kể các lỗ hổng bảo mật. Tại ANT NCC tối ưu hóa hạ tầng và container luôn là một trong những tiêu chí hàng đầu khi triển khai dự án. Bài viết này sẽ chia sẻ với bạn những tuyệt chiêu “ép cân” Docker Image cực kỳ hiệu quả mà ai cũng có thể áp dụng ngay.
1. Tại Sao Docker Image Của Bạn Lại “Béo Phì”?
Trước khi giảm cân, chúng ta cần biết “mỡ thừa” đến từ đâu. Một Docker Image thường bị phình to do 3 nguyên nhân phổ biến sau:
- Chọn sai Base Image: Sử dụng các OS đầy đủ (như Ubuntu, Debian, Centos) thay vì các phiên bản rút gọn.
- Mang theo cả “đồ chơi” của môi trường Development lên Production: Bao gồm các bộ biên dịch (Compilers), source code chưa build, hoặc các thư viện devDependencies.
- Lạm dụng quá nhiều câu lệnh RUN: Mỗi câu lệnh
RUN,COPY,ADDtrong Dockerfile sẽ tạo ra một Layer mới. Nếu không dọn dẹp rác ngay trong chính Layer đó, dung lượng của nó sẽ bị giữ lại mãi mãi.
2. Các Tuyệt Chiêu “Ép Cân” Docker Image Thực Chiến
2.1 Vũ khí tối thượng: Multi-stage Build
Đây là tính năng mạnh mẽ nhất được giới thiệu từ phiên bản Docker 17.05. Hãy tưởng tượng bạn cần build một ứng dụng Go hoặc Node.js: bạn cần rất nhiều công cụ để build, nhưng khi chạy (Run) trên Production, bạn chỉ cần file thực thi (Binary) hoặc folder dist đã được compile.
Multi-stage Build cho phép bạn chia Dockerfile thành nhiều giai đoạn (Stage). Bạn dùng một Image to khỏe ở Stage 1 để build, sau đó chỉ copy kết quả đã build sang Stage 2 (sử dụng một Image cực nhẹ) để chạy.
2.2 Chọn Base Image “siêu mẫu”: Alpine hoặc Distroless
- Alpine Linux: Chỉ nặng khoảng 5MB, được tích hợp sẵn trình quản lý gói
apk. Thay vì dùngnode:20(khoảng 1GB), hãy dùngnode:20-alpine(chỉ khoảng 180MB). - Distroless: Được phát triển bởi Google, Image này loại bỏ hoàn toàn Package Manager, Shell và tất cả các công cụ đi kèm, chỉ để lại duy nhất môi trường chạy ứng dụng. Đây là lựa chọn đỉnh cao về cả dung lượng lẫn bảo mật. Bạn có thể tham khảo thêm tại Google Container Tools (link outbound ra nguồn uy tín).
2.3 Đừng quên file .dockerignore
Tương tự như .gitignore, file này giúp Docker bỏ qua các thư mục “nặng ký” không cần thiết khi thực hiện lệnh COPY . ., ví dụ như: node_modules, .git, dist, hoặc các file cấu hình local.
3. Demo Thực Chiến: Tối Ưu Hóa Dockerfile Cho Ứng Dụng Node.js
Hãy cùng nhìn vào sự khác biệt kinh điển giữa một Dockerfile “ngây thơ” và một Dockerfile đã qua trường lớp tối ưu tại NCC.
Cách viết “thông thường” (Tệ):
Dockerfile
FROM node:20
WORKDIR /app
COPY . .
RUN npm install
EXPOSE 3000
CMD ["npm", "start"]
🔴 Kết quả: Image nặng khoảng 1.1 GB, chứa toàn bộ source code gốc và các công cụ build không cần thiết trên Production.
Cách viết áp dụng Multi-stage Build + Alpine (Chuẩn):
Bạn có thể xem thêm cú pháp chuẩn tại Docker Documentation (link outbound ra tài liệu gốc) để hiểu sâu hơn về cơ chế cache layer.
Dockerfile
# STAGE 1: Build môi trường
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci # Cài đặt sạch sẽ cả devDependencies để build
COPY . .
RUN npm run build
# STAGE 2: Môi trường chạy Production
FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY package*.json ./
RUN npm ci --only=production # Chỉ cài thư viện chạy Production
# Chỉ copy folder code đã được build từ STAGE 1 sang
COPY --from=builder /app/dist ./dist
EXPOSE 3000
CMD ["node", "dist/main.js"]
🟢 Kết quả: Image giảm xuống chỉ còn khoảng 150 MB (Giảm hơn 85% dung lượng!).
4. Bảng So Sánh Hiệu Năng Sau Khi Tối Ưu
Dưới đây là số liệu thực tế được đo đạc sau khi áp dụng các bộ lọc tối ưu hóa cho một project mẫu:
| Tiêu chí | Trước khi tối ưu | Sau khi tối ưu | Trạng thái hệ thống |
| Kích thước Image | 1.15 GB | 148 MB | Giảm ~87% 📉 |
| Thời gian CI/CD Pipeline | 8 phút 45 giây | 1 phút 30 giây | Nhanh hơn 5.8 lần ⚡ |
| Lỗ hổng bảo mật (Vulnerabilities) | > 200 (High/Medium) | 0 – 5 (Low) | An toàn hơn 🛡️ |
5. Kết Luận & Key Takeaways
Tối ưu Docker Image không phải là một công việc làm một lần rồi thôi, mà nó là một tư duy cần có của mọi Backend Engineer và DevOps Engineer.
3 Điều cần nhớ khi viết Dockerfile:
- Hãy luôn chọn phiên bản Alpine hoặc Slim làm Base Image nếu ứng dụng không yêu cầu các thư viện hệ thống đặc thù.
- Sử dụng Multi-stage Build để tách biệt hoàn toàn môi trường Build và môi trường Run.
- Tận dụng tối đa bộ nhớ Cache của Docker bằng cách sắp xếp các câu lệnh ít thay đổi (như cài đặt thư viện) lên trước các câu lệnh hay thay đổi (như copy source code).
