CLASSFUNC BLOG
We Share Our Knowledge
Chúng tôi đã giảm size docker khi build api cho khách hàng từ 1.36 GB xuống 28.63 MB như thế nào?
Lê Thành
28 Th08 2022 16:26

fad7cf1a-772f-43e4-9042-e96d5d903b2b.webp

Chào các bạn.

Lại là tôi, ClassFuncer đây.

Với tiêu chí coi hệ thống của khách hàng như hệ thống của công ty, không những chúng tôi chăm chút code đẹp, code chất lượng, mà chúng tôi còn quan tâm những chi tiết nhỏ nhất để hệ thống nhẹ nhất, chạy nhanh nhất, kết quả là người dùng được trải nghiệm tốt nhất, mang lại giá trị cho cộng đồng.

Hôm nay tôi lại chia sẻ một kiến thức mà đôi khi mình không để ý, đó là size của docker, làm sao giảm được docker size. Chúng ta bắt đầu nhé.

Doker là gì?

Docker có thể hiểu nôm na là có chức năng gói cả 1 hệ điều hành, từ đó deploy hệ thống trên hệ điều hành đó vào trong 1 file duy nhất. Docker đã được đóng gói, vì vậy việc di chuyển qua lại giữa các môi trường một cách dễ dàng hơn.

Tại sao lại phải giảm size docker?

Cũng giống như một file nặng và nhẹ, docker size nhỏ hơn sẽ giúp khởi động hệ thống nhanh hơn, tốn ít ram hơn, ít thải CO2 hơn nên bảo vệ môi trường hơn 😀

Làm gì để giảm size docker?

Theo kinh nghiệm đang deploy hơn 20 hệ thống khác nhau cho khách hàng, mình có rút ra một số điều như sau:

  1. Xác định các file chỉ cần cho image được build ra.
  2. Thiết đặt .dockerignore để giảm thiểu file phải copy vào image của docker.
  3. Chia việc build docker thành các stage khác nhau, chỉ những file cần thiết sẽ có mặt trong docker image cuối cùng.

Chúng ta bắt đầu nhé.

Ví dụ tôi build 1 api được viết bằng Golang, phiên bản chưa tối ưuDockerfile như sau:

FROM golang:1.19-alpine as builder WORKDIR /go/src/app ADD . . COPY .env.production .env RUN go get ./ RUN go build -o server # Run the web service on container startup. CMD ["./server"]

Thực hiện build:

docker build -t brother-api-alpine .

Và 1 Dockerfile được tối ưu có nội dung như sau:

FROM golang:1.19-alpine as build-stage # Stage 1: build distribution files. WORKDIR /dist COPY . . COPY .env.production .env RUN go get ./ RUN go build -o server # Stage 2: build the image FROM alpine WORKDIR /app COPY --from=build-stage /dist/.env ./.env COPY --from=build-stage /dist/server ./server COPY --from=build-stage /dist/static ./static CMD ["./server"]

Thực hiện build

docker build -t brother-api-optimize .

Và chúng ta có 2 docker được sinh ra với size 1.36GB và 28.63MB, một sự khác biệt quá lớn, phải không các bạn 😅?

Ảnh chụp Màn hình 2022-08-28 lúc 19.00.32.png

Tại sao lại khác 🤔?

Có lẽ khi các bạn đọc 2 Dockerfile trên đã thấy sự khác biệt. Ở file docker optimize, mình chia thành 2 stage, 1 cho việc build, và 1 cho docker sẽ được sinh ra và được deploy.

  • Stage 1 mục đích là sinh ra file binary server
  • Stage 2 là sử dụng file server đã được sinh ra ở stage 1

Tại sao? Tại vì tất cả những file trong quá trình build không cần thiết, ví dụ các file trong quá trình COPY và trong quá trình RUN go get ./ ... Mục đích cuối cùng là chúng ta chỉ cần file server được go build ra và một số file liên quan.

Ảnh chụp Màn hình 2022-08-28 lúc 23.05.35.png

Ảnh trên là khi ta inspect image của Docker image đã được build ra với tên brother-api-alpine

So sánh với ảnh dưới (là inspect của Docker image đã được build ra với tên brother-api-optimize

Ảnh chụp Màn hình 2022-08-28 lúc 23.10.12.png

Sự khác biệt quá lớn phải không các bạn?

Thực chất chúng ta chỉ cần file server, file .env và folder static thôi, đúng không 😄?


Kết luận

Cũng như mình đã viết ở trên thôi, kết luận lại là khi build 1 docker image, chúng ta cần:

  1. Xác định các file chỉ cần cho image được build ra.
  2. Thiết đặt .dockerignore để giảm thiểu file phải copy vào image của docker.
  3. Chia việc build docker thành các stage khác nhau, chỉ những file cần thiết sẽ có mặt trong docker image cuối cùng.

ClassFunc đang không ngừng cải tiến chất lượng hệ thống cho khách hàng, cho công ty để cống hiến cộng đồng nhiều hơn.

Nếu các bạn có ý định làm việc về công nghệ thông tin thì đừng ngần ngại liên hệ hello@classfunc.com nhé.

Chúc các bạn buổi tối vui vẻ 😀