Bài viết được sự cho phép của tác giả Tống Xuân Hoài
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="org@example.com"
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:
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.
Bài viết gốc được đăng tải tại 2coffee.dev
Có thể bạn quan tâm:
- Sử dụng miễn phí Docker Registry của Gitlab
- Cài đặt Apache Kafka sử dụng Docker Compose
- Nginx và Apache là gì? So sánh Nginx và Apache
Xem thêm Việc làm IT hấp dẫn trên TopDev