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:
- Xác định các file chỉ cần cho image được build ra.
- Thiết đặt .dockerignore để giảm thiểu file phải copy vào image của docker.
- 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 ưu
có Dockerfile
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 😅?
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 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
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:
- Xác định các file chỉ cần cho image được build ra.
- Thiết đặt .dockerignore để giảm thiểu file phải copy vào image của docker.
- 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ẻ 😀