Các Lỗi Dockerfile Thường Gặp và Mẹo Tối ưu Image Thực tế
Docker là nền tảng quan trọng trong workflow DevOps hiện đại, nhưng Dockerfile thường chưa được tối ưu đúng cách. Bài viết này tổng hợp các lỗi phổ biến và các kỹ thuật tối ưu giúp image nhỏ hơn, build nhanh hơn và an toàn hơn.
Các Lỗi Dockerfile Phổ biến
1. Dùng latest tag
Anti-pattern
FROM node:latest
FROM ubuntu:latestVấn đề: latest là tag mutable, có thể làm build bị vỡ bất ngờ khi upstream release mới.
Giải pháp: Dùng version cụ thể hoặc SHA digest:
# Tốt
FROM node:20.11.0-alpine
# Tốt hơn (an toàn hơn)
FROM node@sha256:abc123def456...2. Không tận dụng layer cache
Common Mistake
FROM node:20-alpine
COPY . .
RUN npm install
RUN npm run buildVấn đề: Mỗi lần source đổi đều làm invalid cache, kể cả khi dependencies không đổi.
Giải pháp: Copy file dependency trước:
FROM node:20-alpine
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build3. Chạy container bằng root
Security Risk
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y nginx
CMD ["nginx", "-g", "daemon off;"]Vấn đề: Root trong container là rủi ro bảo mật lớn.
Giải pháp: Tạo user không phải root:
FROM node:20-alpine
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodejs -u 1001
WORKDIR /app
COPY --chown=nodejs:nodejs . .
USER nodejs
CMD ["node", "index.js"]4. Copy thừa file không cần thiết
COPY . .Vấn đề: Copy cả .git, test, docs, node_modules làm image phình to.
Giải pháp: Dùng .dockerignore:
node_modules
npm-debug.log
.git
.gitignore
.env
coverage
.vscode
*.md
.DS_Store5. Không cleanup cache package manager
FROM ubuntu:22.04
RUN apt-get update
RUN apt-get install -y python3 python3-pip
RUN pip3 install flaskVấn đề: Cache tạm lưu lại làm image nặng.
Giải pháp: Cleanup trong cùng RUN:
FROM ubuntu:22.04
RUN apt-get update && \
apt-get install -y --no-install-recommends python3 python3-pip && \
pip3 install --no-cache-dir flask && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*6. Dùng quá nhiều RUN
Vấn đề: Mỗi RUN tạo một layer mới.
Giải pháp: Gộp command:
FROM ubuntu:22.04
RUN apt-get update && \
apt-get install -y --no-install-recommends curl wget git && \
apt-get clean && \
rm -rf /var/lib/apt/lists/*7. Expose quá nhiều cổng
EXPOSE 80 443 8080 3000 5000Vấn đề: Gây nhiễu cấu hình và tăng bề mặt tấn công.
Giải pháp: Chỉ expose cổng thực sự cần dùng.
EXPOSE 3000Mẹo Tối ưu Image Thực tế
1. Multi-stage build
# Stage 1: Build
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Stage 2: Runtime
FROM node:20-alpine
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package*.json ./
USER nodejs
EXPOSE 3000
CMD ["node", "dist/index.js"]TIP
Giảm đáng kể kích thước image vì không mang theo build tools/source dư thừa.
2. Chọn base image phù hợp
# Alpine (nhỏ nhất)
FROM node:20-alpine
# Distroless (an toàn, tối giản)
FROM gcr.io/distroless/nodejs20-debian12
# Debian slim (cân bằng)
FROM node:20-slimSo sánh nhanh
- Alpine: nhỏ, nhanh, nhưng có thể phát sinh vấn đề tương thích musl
- Distroless: bảo mật tốt, nhưng khó debug hơn
- Debian slim: cân bằng giữa size và tính tương thích
3. Tối ưu thứ tự layer
Sắp xếp từ ít thay đổi đến hay thay đổi:
- Base image
- System packages
- Dependencies
- Source code
- Runtime config
4. Dùng .dockerignore kỹ
Nên loại trừ:
- Dependencies local (
node_modules) - VCS (
.git) - IDE files (
.vscode,.idea) - Env files (
.env*) - Test & coverage
- Build artifacts
Checklist Production
- [ ] Không dùng
latest - [ ] Chạy với non-root user
- [ ] Có
.dockerignoređúng chuẩn - [ ] Sử dụng multi-stage build
- [ ] Gộp
RUNhợp lý và cleanup cache - [ ] Chỉ expose cổng cần thiết
- [ ] Pin version base image/dependency
Kết luận
Dockerfile tốt không chỉ giúp build nhanh hơn mà còn giảm chi phí runtime và tăng mức độ an toàn khi vận hành. Bắt đầu từ những tối ưu nhỏ như layer cache, non-root, multi-stage, bạn sẽ thấy khác biệt rõ ràng khi scale.
