0
0
Lập trình
Admin Team
Admin Teamtechmely

Giảm kích thước Docker Image từ 1.2GB xuống 54MB

Đăng vào 7 tháng trước

• 4 phút đọc

Giảm Kích Thước Docker Image từ 1.2GB xuống 54MB

Khi tôi lần đầu tiên container hóa ứng dụng Node.js của mình, tôi cảm thấy khá tự hào. Tôi đã có một Dockerfile, tôi đã xây dựng nó và nó hoạt động.

Rồi tôi kiểm tra kích thước.

1.2GB. Cho một dịch vụ Node.js duy nhất.

Đó là lúc thực tế ập đến. Hình ảnh của tôi không gọn gàng—nó quá cồng kềnh. Nó làm chậm quá trình xây dựng, làm nặng nề quy trình CI/CD, mất rất nhiều thời gian để đẩy lên registry và chiếm dụng dung lượng lưu trữ như không có ngày mai.

Vì vậy, tôi đã đặt hình ảnh Docker của mình vào một chế độ ăn kiêng nghiêm ngặt. Sau vài lần tối ưu hóa, nó đã giảm từ 1.2GB → 250MB → 54MB.

Dưới đây là câu chuyện về cách tôi cắt bỏ những phần thừa—và cách bạn có thể làm điều tương tự.

Bước 1: Khởi Đầu Nặng Nề

Dưới đây là cách mà Dockerfile ban đầu của tôi trông như thế nào:

dockerfile Copy
FROM node:16

WORKDIR /app

COPY package*.json ./
RUN npm install

COPY . .

CMD ["node", "server.js"]

Trông có vẻ vô hại, phải không? Nhưng nó có vài vấn đề:

  • node:16 dựa trên Debian và nặng (~350MB).
  • npm install cài đặt mọi thứ—bao gồm cả các phụ thuộc phát triển và sản xuất.
  • Không có .dockerignore, vì vậy nhật ký, lịch sử git và node_modules đã lén vào hình ảnh.

Kết quả? Một quái vật 1.2GB làm chậm mọi thứ.

Bước 2: Chọn Một Cơ Sở Nhẹ Hơn

Sửa đổi đầu tiên là thay thế node:16 bằng node:16-alpine.

dockerfile Copy
FROM node:16-alpine

Chỉ với một dòng thay đổi, hình ảnh của tôi đã giảm xuống còn ~250MB.

Bài học: Lựa chọn hình ảnh cơ sở của bạn có thể quyết định sự thành công hay thất bại trong quá trình xây dựng.

⚠️ Lưu ý: Alpine sử dụng musl thay vì glibc. Nếu ứng dụng của bạn có các mô-đun gốc (sharp, bcrypt, canvas), bạn có thể cần thêm các gói.

Bước 3: Xây Dựng Đa Giai Đoạn

Ứng dụng của tôi sử dụng TypeScript, vì vậy tôi đã có các công cụ xây dựng nằm trong hình ảnh cuối cùng. Đây là một sai lầm lớn. Chúng thêm hàng trăm MB mà tôi không cần trong môi trường sản xuất.

Giới thiệu về xây dựng đa giai đoạn:

dockerfile Copy
# Giai đoạn 1: Builder
FROM node:16-alpine AS builder

WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Giai đoạn 2: Runtime
FROM node:16-alpine

WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY package*.json ./
RUN npm ci --only=production

CMD ["node", "dist/server.js"]

Bây giờ, hình ảnh cuối cùng chỉ chứa:

  • JavaScript đã biên dịch (dist/)
  • Các phụ thuộc sản xuất

Không có phụ thuộc phát triển. Không có bộ nhớ đệm xây dựng. Không có sự lộn xộn.

Điều này đã giảm hình ảnh của tôi xuống còn ~120MB.

Bước 4: Dọn Dẹp và Bỏ Qua Rác

Một thủ phạm khác: các tệp không nên có trong môi trường sản xuất.

Tôi đã thêm một .dockerignore:

dockerignore Copy
node_modules
npm-debug.log
Dockerfile
.dockerignore
.git
.gitignore
*.md
tests

Và tôi đã dọn dẹp bộ nhớ đệm trong Dockerfile:

dockerfile Copy
RUN npm ci --only=production \
    && npm cache clean --force \
    && rm -rf /tmp/*

Kết quả cuối cùng: không có rác rưởi nào, không có MB nào bị lãng phí.

Bước 5: Giảm Thiểu Các Lớp

Ban đầu, tôi đã có một Dockerfile với nhiều câu lệnh RUN:

dockerfile Copy
RUN apk add --no-cache python3
RUN npm ci --only=production
RUN npm cache clean --force

Mỗi RUN thêm một lớp. Tôi đã kết hợp chúng thành một:

dockerfile Copy
RUN apk add --no-cache python3 \
    && npm ci --only=production \
    && npm cache clean --force

Sự điều chỉnh nhỏ này đã giảm xuống khoảng ~15MB. Không lớn, nhưng mỗi MB đều quan trọng khi bạn đang kéo hình ảnh trong môi trường sản xuất.

Bước 6: Đo Lường và Lặp Lại

Chìa khóa để giảm kích thước hình ảnh là đo lường:

bash Copy
docker images
docker history <image>

Với docker history, tôi đã thấy chính xác lớp nào đang chiếm không gian và tối ưu hóa từ đó.

Kiểm Tra Cân Nặng Cuối Cùng

  • Ban đầu: 1.2GB
  • Sau khi chuyển sang Alpine: ~250MB
  • Sau khi xây dựng đa giai đoạn + dọn dẹp: 120MB
  • Sau khi thêm .dockerignore + dọn dẹp: 54MB 🎉

Đó là một giảm ~95%. Thời gian kéo hình ảnh từ phút xuống giây, và quy trình CI/CD không còn chậm chạp nữa.

Bài Học Rút Ra

  1. Chọn hình ảnh cơ sở đúng – Các tùy chọn mặc định hiếm khi tối ưu.
  2. Xây dựng đa giai đoạn là vàng – Giữ công cụ phát triển ra khỏi môi trường sản xuất.
  3. Sử dụng .dockerignore một cách nghiêm túc – Đừng gửi rác.
  4. Dọn dẹp một cách mạnh mẽ – Bộ nhớ đệm, nhật ký, tệp tạm… hãy xóa chúng.
  5. Đo lường liên tục – Biết điều gì đang chiếm không gian trước khi khắc phục nó.

Kết Luận

Giảm kích thước hình ảnh Docker không chỉ là vấn đề khoe khoang—đó là về việc triển khai nhanh hơn, giảm chi phí registry và ít đau đầu hơn.

Hình ảnh Node.js của tôi đã giảm 1.1GB, và tôi sẽ không bao giờ quay lại với những Dockerfile lười biếng nữa.

Nếu các container của bạn đang cồng kềnh, hãy tin tôi: một vài điều chỉnh có thể làm cho chúng nhẹ như lông vũ.

Vậy… hình ảnh Docker của bạn có đang trong chế độ ăn kiêng lành mạnh không?

📬 Liên Hệ

Nếu bạn muốn kết nối, hợp tác hoặc thảo luận về DevOps, hãy cảm thấy tự do liên hệ với tôi:

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào