Tối ưu Docker Image: Giảm kích thước, tăng tốc Build và Deploy
Docker giúp chúng ta đóng gói ứng dụng cùng toàn bộ môi trường cần thiết để chạy ứng dụng. Tuy nhiên, nếu Docker Image quá lớn, quá trình Build, Push, Pull và Deploy sẽ trở nên chậm hơn và tiêu tốn nhiều tài nguyên.
Trong bài viết này, chúng ta sẽ tìm hiểu những kỹ thuật quan trọng giúp tối ưu Docker Image, giảm kích thước Image và cải thiện hiệu suất triển khai.
1. Vì sao cần tối ưu Docker Image?
Một Docker Image lớn có thể gây ra nhiều vấn đề:
- Thời gian Build lâu.
- Push và Pull Image chậm.
- Tốn nhiều dung lượng lưu trữ trên Docker Registry.
- Tốn băng thông khi Deploy.
- Thời gian triển khai lâu hơn.
- Có thể chứa nhiều package không cần thiết và làm tăng rủi ro bảo mật.
Ví dụ, nếu một Image có kích thước 1.5GB nhưng sau khi tối ưu chỉ còn 300MB, tốc độ Push, Pull và Deploy có thể được cải thiện đáng kể.
2. Chọn Base Image phù hợp
Base Image là nền tảng để xây dựng Docker Image và có ảnh hưởng lớn đến kích thước Image cuối cùng.
Ví dụ:
FROM ubuntu:24.04
Nếu ứng dụng chỉ cần PHP, chúng ta có thể sử dụng Image PHP trực tiếp:
FROM php:8.4-fpm
Trong một số trường hợp, có thể sử dụng Alpine:
FROM php:8.4-fpm-alpine
Alpine thường có kích thước nhỏ hơn đáng kể. Tuy nhiên, không phải ứng dụng nào cũng phù hợp với Alpine vì một số package hoặc extension có thể yêu cầu thêm cấu hình.
3. Sử dụng Multi-stage Build
Multi-stage Build là một trong những kỹ thuật quan trọng nhất để giảm kích thước Docker Image.
Ví dụ, khi Build một ứng dụng Frontend, chúng ta cần Node.js và nhiều package Development trong quá trình Build. Tuy nhiên, Production chỉ cần các file đã được Build.
FROM node:24 AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build
FROM nginx:alpine COPY --from=builder /app/dist /usr/share/nginx/html
Trong ví dụ trên, Node.js và toàn bộ package phục vụ quá trình Build không được đưa vào Production Image.
Kết quả là Image Production có thể nhỏ hơn rất nhiều so với việc sử dụng một Image duy nhất.
4. Sử dụng .dockerignore
Khi sử dụng:
COPY . .
Docker sẽ lấy dữ liệu từ Build Context. Nếu không có .dockerignore, nhiều file không cần thiết có thể bị đưa vào quá trình Build.
Ví dụ file .dockerignore:
.git node_modules vendor .env .idea .vscode storage/logs *.log
Việc sử dụng .dockerignore giúp giảm Build Context, tăng tốc quá trình Build và tránh đưa những dữ liệu không cần thiết vào Image.
5. Tận dụng Docker Cache
Docker có cơ chế Layer Cache giúp các bước Build không thay đổi được sử dụng lại.
Ví dụ với Node.js, thay vì:
COPY . . RUN npm install
Nên tách dependency ra trước:
COPY package.json package-lock.json ./ RUN npm ci COPY . .
Khi source code thay đổi nhưng file dependency không thay đổi, Docker có thể sử dụng lại Layer đã được Cache.
Điều này giúp giảm đáng kể thời gian Build.
6. Giảm số lượng Layer không cần thiết
Mỗi lệnh RUN, COPY hoặc ADD có thể tạo ra một Layer.
Thay vì:
RUN apt update RUN apt install -y curl RUN apt clean
Có thể gộp lại:
RUN apt update &&
apt install -y curl &&
apt clean &&
rm -rf /var/lib/apt/lists/*
Cách này giúp kiểm soát tốt hơn các Layer và loại bỏ cache không cần thiết.
7. Chỉ cài đặt dependency cần thiết
Production Image không nên chứa các package chỉ phục vụ Development.
Ví dụ với Laravel:
composer install --no-dev --prefer-dist --optimize-autoloader
Với Node.js:
npm ci --omit=dev
Việc loại bỏ Development Dependency giúp Image nhỏ hơn và giảm số lượng package cần kiểm tra về mặt bảo mật.
8. Xóa cache sau khi cài package
Package manager thường tạo ra cache trong quá trình cài đặt.
Ví dụ với Alpine:
RUN apk add --no-cache nginx
Với Debian/Ubuntu:
RUN apt update &&
apt install -y curl &&
rm -rf /var/lib/apt/lists/*
Việc xóa cache giúp giảm kích thước Image cuối cùng.
9. Kiểm tra Docker Image
Sau khi Build, có thể kiểm tra kích thước Image bằng:
docker images
Để xem các Layer:
docker history image_name
Ngoài ra, các công cụ như Dive, Trivy hoặc Docker Scout có thể được sử dụng để phân tích Layer và kiểm tra các vấn đề bảo mật.
10. Checklist tối ưu Docker Image
- Chọn Base Image phù hợp.
- Sử dụng Multi-stage Build.
- Tạo file .dockerignore.
- Tận dụng Docker Cache.
- Không cài package không cần thiết.
- Xóa package cache.
- Chỉ cài Production Dependency.
- Kiểm tra kích thước các Layer.
- Scan Image để phát hiện lỗ hổng bảo mật.
Kết luận
Tối ưu Docker Image không chỉ giúp giảm dung lượng mà còn cải thiện đáng kể tốc độ Build, Push, Pull và Deploy.
Đối với các dự án sử dụng CI/CD hoặc Microservices, việc giữ Docker Image nhỏ và tối ưu sẽ giúp tiết kiệm thời gian, tài nguyên và chi phí vận hành.
Trong thực tế, chỉ cần áp dụng tốt Multi-stage Build, .dockerignore, Docker Cache và lựa chọn Base Image phù hợp, bạn đã có thể giảm đáng kể kích thước Docker Image.