Docker Best Practices: Tối ưu Dung lượng Docker Image

container layer

Docker đóng gói ứng dụng và tất cả các phụ thuộc vào một container, giúp đảm bảo tính nhất quán giữa các môi trường khác nhau. Tuy nhiên, một trong những thách thức lớn khi làm việc với Docker là tạo ra Docker image gọn nhẹ và tối ưu hóa về tốc độ.

Trong bài viết này, mình sẽ hướng dẫn các bạn cách tối ưu hóa Docker image cách hiệu quả để giúp bạn giảm dung lượng, tăng tốc độ build và đảm bảo bảo mật tốt hơn cho container của bạn.

1. Tại sao phải tối ưu dung lượng docker image?

2. Tối ưu dung lượng Image

2.1 Minimal Base Images

Một trong những bước quan trọng nhất để tối ưu hóa Docker image là chọn base image (image nền) phù hợp.

Base image cơ bản được sử dụng để xây dựng Docker image của bạn. Chọn một base image nhẹ sẽ giúp bạn giảm đáng kể kích thước của image cuối cùng.

Khi bạn sử dụng base image tối thiểu, bạn có thể giảm kích thước tổng thể của Docker image và cải thiện bảo mật.

2.2 Multi-stage Builds: The Secret Sauce

Multi-stage builds là kỹ thuật tối ưu hóa Docker image bằng cách sử dụng nhiều giai đoạn để tách việc xây dựng và chạy ứng dụng. Điều này cho phép bạn chỉ sao chép những phần cần thiết từ giai đoạn build vào image cuối cùng, giúp giảm kích thước image đáng kể.

Ví dụ, đối với ứng dụng Go, bạn có thể sử dụng multi-stage builds như sau:

Dockerfile

FROM golang:1.16-alpine AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp

FROM alpine:3.18
WORKDIR /app
COPY --from=builder /app/myapp .
CMD ["./myapp"]

Trong ví dụ trên, giai đoạn đầu sẽ biên dịch ứng dụng Go, chỉ có file nhị phân cuối cùng được sao chép vào image production. Nhờ có multi-stage builds, bạn tránh được việc bao gồm các công cụ build không cần thiết vào image cuối cùng.

Mình sẽ lấy thêm ví dụ đối với ứng dụng Nodejs:

Dockerfile

FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json tsconfig.json ./
RUN npm install
COPY . .
RUN npm run build

FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY package*.json ./
RUN npm install --only=production
CMD ["node", "dist/index.js"]

Giai đoạn build (builder):

Giai đoạn chạy:

2.3 Layer Optimization: Every Line Counts

Docker xây dựng image thành từng lớp (layer), mỗi lệnh trong Dockerfile sẽ tạo ra một lớp mới. Nên là, việc tối ưu hóa cách mà bạn viết Dockerfile cũng cực kỳ quan trọng để giảm thiểu số lớp và kích thước image.

Đây là một ví dụ về không tối ưu trong Go và TypeScript:

Dockerfile

//Go
RUN apt-get update
RUN apt-get install -y python
RUN apt-get clean

//TypeScript
RUN npm install -g typescript
RUN npm install -g ts-node
RUN npm install

Và sau khi mình áp dụng tối ưu sẽ như này:

Dockerfile

//Go
RUN apt-get update && 
    apt-get install -y python && 
    apt-get clean && 
    rm -rf /var/lib/apt/lists/*

//TypeScript
RUN npm install -g typescript ts-node && 
    npm install

Đây là một ví dụ chưa được tối ưu:

Dockerfile

//Go
COPY . .
RUN pip install -r requirements.txt

//TypeScript
COPY . .
RUN npm install

Trong trường hợp này, nếu bạn thay đổi bất kỳ file nào, Docker sẽ phải chạy lại lệnh pip install đối với Go và npm install đối với TypeScript.

Dockerfile

//Go
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .

//TypeScript
COPY package*.json ./
RUN npm install
COPY . .

Bằng cách này, nếu code thay đổi nhưng requirements.txt hay package.json không đổi, Docker sẽ sử dụng cache cho bước cài đặt thư viện, giúp tăng tốc độ build.

Việc này sẽ đảm bảo bước cài đặt phụ thuộc được cache lại, giúp quá trình build nhanh hơn khi chỉ có code thay đổi.

2.4 Sử dụng .dockerignore

File .dockerignore cũng tương tự như .gitignore, giúp loại bỏ những file và thư mục không cần thiết khỏi quá trình build. Điều này không chỉ giúp giảm kích thước build context mà còn bảo vệ các file nhạy cảm khỏi việc vô tình được thêm vào image.

Ví dụ .dockerignore

Dockerignore

node_modules
.git
.env
Dockerfile
README.md

Việc loại bỏ các folder có dung lượng lớn như node_modules hoặc .git khỏi build context sẽ làm cho quá trình build nhanh và gọn nhẹ hơn.

2.5 Sử dụng Docker’s BuildKit

Docker BuildKit là tính năng mới của Docker giúp cải thiện hiệu suất build và cung cấp các options mới cho việc tối ưu Dockerfile. Để kích hoạt BuildKit, bạn chỉ cần thêm biến môi trường DOCKER_BUILDKIT=1 khi chạy lệnh build.

Bash

DOCKER_BUILDKIT=1 docker build .

Một vài lợi ích của BuildKit bao gồm:

2.6 Loại bỏ file và folder không cần thiết

Trong quá trình build, có thể sẽ phát sinh các file tạm, cache hoặc log không cần thiết cho image cuối cùng. Bạn nên kiểm tra và loại bỏ giúp giảm kích thước image.

Xoá cache và file tạm:

Dockerfile

RUN apt-get update && 
    apt-get install -y package && 
    apt-get clean && 
    rm -rf /var/lib/apt/lists/*

Xoá file log và docs:

Dockerfile

RUN rm -rf /var/log/* /usr/share/doc/*

2.7 Giảm số lượng Dependencies

Cài đặt ít dependencies hơn sẽ tối ưu về mặt kích thước image.

Chỉ cài đặt những gì cần thiết:

Dockerfile

RUN apt-get install -y --no-install-recommends package

--no-install-recommends sẽ chỉ cài đặt những package cần thiết, bỏ qua các package khuyến nghị không bắt buộc.

3. Kết luận

Tối ưu hóa là một quá trình liên tục. Hy vọng qua những chia sẻ trong bài viết, bạn có thể áp dụng tối ưu docker image của cá nhân bạn. Bên cạnh đó bạn nên thường xuyên cập nhật các kiến thức và công cụ mới để đảm bảo Docker image của mình luôn trong trạng thái tốt nhất.

Các bài viết liên quan:

Exit mobile version