Skip to content

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

dockerfile
FROM node:latest
FROM ubuntu:latest

Vấ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:

dockerfile
# 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

dockerfile
FROM node:20-alpine
COPY . .
RUN npm install
RUN npm run build

Vấ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:

dockerfile
FROM node:20-alpine

COPY package*.json ./
RUN npm ci --only=production

COPY . .
RUN npm run build

3. Chạy container bằng root

Security Risk

dockerfile
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:

dockerfile
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

dockerfile
COPY . .

Vấn đề: Copy cả .git, test, docs, node_modules làm image phình to.

Giải pháp: Dùng .dockerignore:

txt
node_modules
npm-debug.log
.git
.gitignore
.env
coverage
.vscode
*.md
.DS_Store

5. Không cleanup cache package manager

dockerfile
FROM ubuntu:22.04
RUN apt-get update
RUN apt-get install -y python3 python3-pip
RUN pip3 install flask

Vấn đề: Cache tạm lưu lại làm image nặng.

Giải pháp: Cleanup trong cùng RUN:

dockerfile
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:

dockerfile
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

dockerfile
EXPOSE 80 443 8080 3000 5000

Vấ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.

dockerfile
EXPOSE 3000

Mẹo Tối ưu Image Thực tế

1. Multi-stage build

dockerfile
# 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

dockerfile
# 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-slim

So 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:

  1. Base image
  2. System packages
  3. Dependencies
  4. Source code
  5. 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 RUN hợ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.

Được phát hành theo giấy phép MIT.