Hiểu cơ chế layer caching khi build docker image để viết Dockerfile tốt hơn

Hiểu cơ chế layer caching khi build docker image để viết Dockerfile tốt hơn

Threads
  • Có bạn nào trong lúc code mà bị "ngẫn tò te" hoặc "lú lẫn" trong mớ hỗn độn của mình viết ra chưa. Những lúc như thế tôi thường hay ngừng lại, thư giãn đầu óc, hoặc để mai tính tiếp. Ấy vậy mà rất hiệu quả nhé! Lúc sau xem lại cái tự nhiên thấy vấn đề ở đâu ngay.

    Hoặc cũng có thể thử áp dụng phương pháp "chú vịt vàng" - thử giải thích vấn đề đang gặp phải với vịt xem, nó sẽ cho thấy mâu thuẫn trong lời nói ra.

    Còn không có tiền mua vịt to thì xe túi mù ra vịt bé giống mình nè 😅

    » Xem thêm
  • Ơ buồn cười thật. Ai cũng biết GIF là định dạng ảnh động thường được dùng thay cho video clip để hiển thị các nội dung ngắn trên nền tảng web. GIF tiện hơn các nội dung dạng video là vì nó được hiển thị như một bức ảnh và được hỗ trợ rộng rãi. Cơ mà GIF có dung lượng nặng quá.

    Nói thật nhiều lúc mình có vài cái hành động muốn hiển thị lên web cho mọi người xem, cơ mà định dạng GIF nó nặng với cả cũng không biết cách tối ưu cho nhẹ xuống. Hôm nay lên mạng tìm hiểu xem định dạng nào có khả năng thay thế GIF trong tương lai thì mọi người biết đó là gì không? Là WEBP (webp)!!! Đúng vậy, là định dạng ảnh mà mình đang dùng trên blog lâu nay luôn á, mà giờ mới biết là nó hiển thị được cả ảnh động nữa, hơi quê 😆

    Kết hợp với ffmpeg nữa là chuyển được tất tần tật video clip thành webp được ngay. Để vài nửa ngồi chế lại cái cli một tí là dùng ngon luôn mọi người ạ 🤪

    » Xem thêm
  • Cảm giác như Github Copilot đang cố gắng mở rộng thị trường cho anh em developer á. Mới trước họ ra mắt Github Open Copilot Chat thì mới đây lại thêm cái Using GitHub Copilot in the command line dùng để giải thích hoặc gợi ý lệnh trong terminal.

    Đây, cách dùng rất đơn giản thôi, ví dụ muốn nó giải thích câu lệnh sudo apt-get để làm gì, thì:

    $ gh copilot explain "sudo apt-get"

    Hoặc nhờ nó gợi ý lệnh mong muốn, sử dụng tiếng Việt được luôn nhé (kể cả tiếng Việt không dấu vẫn hiểu 😳)

    $ gh copilot suggest "xoá commit chưa push"

    Mình đã kiểm tra và thấy lệnh ra rất đúng, xịn thật 🤓

    » Xem thêm

Vấn đề

Docker gần đây đang nổi đình đám trong cộng đồng IT nên ngày càng phổ biến, được nhiều người dùng hơn. Bằng chứng là tần suất từ Docker xuất hiện trong JD của nhà tuyển dụng ngày càng nhiều. Công ty của tôi sử dụng Docker, dự án của tôi cũng dùng Docker, dự án làm cho người khác cũng dùng nó... Docker xuất hiện như một giải pháp "đóng gói" quá thuận lợi cho cuộc cách mạng tự động hóa.

Nhưng có một điều đã tồn tại song song với nó từ xưa đến này là vấn đề build docker image khá tốn thời gian. Dung lượng của một "hình ảnh" docker nhiều khi lên đến cả hàng GB. Docker bổng nhiên trở thành một "sát thủ ổ cứng". Nhiều câu nói đùa rằng, ông bạn có đủ ổ cứng không mà dám CI/CD với Docker? Nhưng trong bài viết này, tôi không nói về vấn đề nó ngốn dung lượng như thế nào, mà tập trung vào cách làm sao để giảm được tốc độ build docker image.

Có một vài cách để tăng tốc độ build cũng như làm giảm kích thước của docker image như chỉ cài đặt các gói cần thiết, sử dụng các hình ảnh cơ bản nhẹ (alpine), sử dụng ít layer nhất có thể... Chúng đều xoay quanh vấn đề là giữ cho docker tải xuống các tệp cần thiết ít nhất và nhẹ nhất.

Ngoài ra, còn một cách để tăng tốc là tận dụng layer caching của Docker. Vậy nó là gì thì xin mời bạn đọc tiếp bài viết dưới đây.

Sử dụng thứ tự lớp hình ảnh để có lợi cho bạn

Docker image được tạo thành từ các lớp (layer) xếp chồng lên nhau. Mỗi layer đại diện cho một hướng dẫn trong Dockerfile của image. Ví dụ một file Dockerfile như sau:

FROM ubuntu:18.04
LABEL org.opencontainers.image.authors="[email protected]"
COPY . /app
RUN make /app
RUN rm -r $HOME/.cache
CMD python /app/app.py

Mỗi dòng đại diện cho một layer, chúng có kích thước khác nhau và phụ thuộc vào lượng công việc mà chúng làm. Tổng dung lượng của các layer tạo thành dung lượng của image. Chính vì thế, layer càng nhiều và càng nặng thì image càng to. Để hiểu rõ hơn, hãy sử dụng lệnh docker history <image> để biết chi tiết về các lớp tạo thành image.

Ví dụ dưới đây là các lớp và dung lượng của một redislabs/redisearch image:

$ docker history redislabs/redisearch

Kết quả giống như sau:

docker history redislabs/redisearch

Mỗi lần sử dụng lệnh docker build image, docker sẽ phải chạy qua lần lượt từng layer. Nhưng nếu tận dụng layer caching, docker chỉ thực sự tạo lại các lớp bắt đầu từ lớp có sự thay đổi trở về sau. Điều này đồng nghĩa với việc các layer không bị thay đổi đổ về trước có thời gian thực hiện gần như ngay lập tức. Nghĩa là bạn chỉ tốn thời gian cho lần chạy đầu tiên, ở các lần chạy sau đó docker sẽ tận dụng cache để build image.

Ví dụ dưới đây là một Dockerfile của ứng dụng viết bằng Node.js.

FROM node:18-alpine

WORKDIR /app

COPY . .

RUN npm install

Các gói phụ thuộc (dependencies) là rất ít khi bị thay đổi (thêm/sửa/xóa), cho nên khả năng sử dụng lệnh npm install là rất hiếm. Nhưng trong ví dụ trên, rõ ràng dòng lệnh COPY đã làm xáo trộn, gây ra sự thay đổi của layer nên theo lẽ thường, tất cả layer phía sau nó phải được thực hiện mà không có bộ đệm. Bạn sẽ tốn thời gian lẫn băng thông mạng để chạy lệnh npm install sau đó. Đây quả thực là cơn "ác mộng" trong mùa đứt cáp này.

Để tận dụng được cơ chế layer caching, hãy sửa và sắp xếp lại thứ tự layer một cách hợp lý hơn như sau.

FROM node:18-alpine

WORKDIR /app

COPY package*.json ./
RUN npm ci

COPY . .

Có thể thấy nếu package hoặc package-lock.json thay đổi, npm ci sẽ được thực hiện. Còn nếu không thì 2 lệnh trên có thời gian thực hiện gần như là ngay lập tức.

Tổng kết

Có một vài cách để tăng tốc độ build docker image cũng như làm giảm kích thước của docker image. Trong số đó là tận dụng cơ chế layer caching mà docker cung cấp để sắp xếp thứ tự các layer sao cho đạt được ít nhất sự thay đổi, từ đó tăng tốc độ xây dựng các hình ảnh của bạn.

Tham khảo:

hoặc
* Bản tin tổng hợp được gửi mỗi 1-2 tuần, huỷ bất cứ lúc nào.
Author

Xin chào, tôi tên là Hoài - một anh Dev kể chuyện bằng cách viết ✍️ và làm sản phẩm 🚀. Với nhiều năm kinh nghiệm lập trình, tôi đã đóng góp một phần công sức cho nhiều sản phẩm mang lại giá trị cho người dùng tại nơi đang làm việc, cũng như cho chính bản thân. Sở thích của tôi là đọc, viết, nghiên cứu... Tôi tạo ra trang Blog này với sứ mệnh mang đến những bài viết chất lượng cho độc giả của 2coffee.dev.Hãy theo dõi tôi qua các kênh LinkedIn, Facebook, Instagram, Telegram.

Bạn thấy bài viết này có ích?
Không

Bình luận (0)

Nội dung bình luận...