Làm thế nào để tạo hình ảnh docker làm việc nhỏ nhất mỗi lần?


19

Mục đích: để tạo ra các hình ảnh docker làm việc nhỏ nhất mỗi lần

Hiện hành

REPOSITORY          TAG       IMAGE ID            CREATED             SIZE
a-docker-image      latest    x                   42 minutes ago       1.92 GB

Cố gắng

Thêm một bước dọn dẹp ở cuối Dockerfile:

#clean
RUN apt-get purge -y wget
RUN rm -r a-build-dir
RUN apt-get purge -y a-package

giảm kích thước hình ảnh một chút:

REPOSITORY          TAG       IMAGE ID            CREATED             SIZE
a-docker-image      latest    y                   2 minutes ago       1.86 GB

Thảo luận

Tôi đã xây dựng nhiều hình ảnh docker. Mỗi lần tôi cố gắng giảm kích thước của hình ảnh được tạo ra, nhưng tôi luôn cảm thấy nó quá lớn. Tôi đang tìm kiếm một tập lệnh đã được tạo bởi ai đó trên github để loại bỏ tất cả các gói không cần thiết khỏi hình ảnh để kích thước của hình ảnh được tạo sẽ càng nhỏ càng tốt.

Như tôi đã nói, tôi luôn cố gắng giảm kích thước của hình ảnh, nhưng tôi muốn áp dụng sự nhất quán này để mọi hình ảnh mà tôi tạo ra từ bây giờ sẽ nhỏ nhất có thể.

Câu hỏi

Làm thế nào để tạo hình ảnh docker làm việc nhỏ nhất mỗi lần?

Câu trả lời:


1

Có một loạt các kỹ thuật liên quan, không có giải pháp duy nhất. Bạn có thể muốn thực hiện một số điều sau đây:


Đầu tiên, tối ưu hóa các lớp hình ảnh của bạn để tái sử dụng. Đặt các bước thay đổi thường xuyên sau này trong Dockerfile để tăng cơ hội các lớp đầu được lưu vào bộ đệm từ các bản dựng trước. Một lớp được sử dụng lại sẽ hiển thị nhiều không gian đĩa hơn trong một docker image ls, nhưng nếu bạn kiểm tra hệ thống tập tin cơ bản, chỉ có một bản sao của mỗi lớp được lưu trữ trên đĩa. Điều đó có nghĩa là 3 hình ảnh mỗi tệp 2 GB, nhưng chỉ có 50 MB khác nhau trong một vài lớp cuối cùng, sẽ chỉ chiếm 2,1 GB dung lượng đĩa, mặc dù danh sách cho thấy họ đang sử dụng 6 GB kể từ khi bạn đếm gấp đôi mỗi lớp được sử dụng lại.

Tái sử dụng lớp là lý do tại sao bạn thấy hình ảnh với các phụ thuộc xây dựng thay đổi không thường xuyên cài đặt những cái đầu tiên trước khi sao chép mã. Xem bất kỳ ví dụ python có mẫu như:

FROM python
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
# note how the code is copied only after the pip install
# since code changes but requirements.txt doesn't
COPY . .
CMD ["gunicorn", "app:app"]

Chọn một hình ảnh cơ sở tối thiểu. Đây là lý do tại sao bạn thấy mọi người đi từ ubuntuđến debian:slim(các biến thể mỏng có kích thước nhỏ, vận chuyển với các công cụ ít hơn), hoặc thậm chí alpine. Điều này làm giảm kích thước điểm bắt đầu của bạn và rất hữu ích nếu bạn liên tục kéo các phiên bản mới của hình ảnh cơ sở. Tuy nhiên, nếu hình ảnh cơ sở của bạn hiếm khi thay đổi, việc sử dụng lại lớp sẽ loại bỏ phần lớn lợi thế của hình ảnh cơ sở tối thiểu.

Hình ảnh cơ sở nhỏ nhất bạn có thể chọn là scratch, không có gì, không có shell hoặc thư viện và chỉ hữu ích với các nhị phân được biên dịch tĩnh. Mặt khác, chọn một hình ảnh cơ bản bao gồm các công cụ bạn cần mà không có nhiều công cụ bạn không cần.


Tiếp theo, bất kỳ bước nào thay đổi hoặc xóa tệp nên được kết hợp với các bước trước đó tạo tệp đó. Mặt khác, hệ thống tệp lớp, sử dụng sao chép trên ghi ngay cả trên những thứ như thay đổi quyền truy cập tệp, sẽ có tệp gốc ở lớp trước và kích thước hình ảnh sẽ không co lại khi bạn xóa tệp. Đây là lý do tại sao các rmlệnh của bạn không có ảnh hưởng đến không gian đĩa kết quả. Thay vào đó, bạn có thể xâu chuỗi các lệnh, như:

RUN apt-get update \
 && apt-get install -y \
      a-package \
      wget \
 && ... \
 && apt-get purge -y wget \
 && rm -r a-build-dir \
 && apt-get purge -y a-package

Lưu ý rằng việc lạm dụng chuỗi lệnh có thể làm chậm các bản dựng của bạn vì bạn cần cài đặt lại bộ công cụ tương tự bất cứ khi nào một điều kiện tiên quyết thay đổi (ví dụ: mã được kéo bằng wget). Xem nhiều giai đoạn dưới đây để thay thế tốt hơn.


Bất kỳ tệp nào bạn tạo mà bạn không cần trong ảnh kết quả sẽ bị xóa, trong bước tạo tệp đó. Điều này bao gồm bộ đệm gói, nhật ký, trang man, v.v. trên máy chủ của bạn) hoặc bạn có thể xây dựng hình ảnh docker của mình mà không cần cắt các container trung gian và sau đó xem diff với:

# first create and leave containers from any RUN step using options on build
docker image build --rm=false --no-cache -t image_name . 
# review which layers use an unexpectedly large amount of space
docker image history image_name
# list all containers, particularly the exited ones from above
docker container ps -a 
# examine any of those containers
docker container diff ${container_id} 
# ... repeat the diff for other build steps
# then cleanup exited containers
docker container prune

Với mỗi người trong số những container trung gian, các diff sẽ hiển thị những tập tin được thêm vào, thay đổi, hoặc xóa trong bước đó (đây là những chỉ báo bằng một A, Choặc Dtrước mỗi tên tập tin). Điều khác biệt đang hiển thị là hệ thống tập tin đọc / ghi cụ thể của bộ chứa, đây là bất kỳ tập tin nào được bộ chứa thay đổi từ trạng thái hình ảnh bằng cách sử dụng bản sao ghi.


Cách tốt nhất để giảm kích thước hình ảnh là loại bỏ mọi thành phần không cần thiết, như trình biên dịch, khỏi hình ảnh vận chuyển của bạn. Do đó, các bản dựng nhiều giai đoạn cho phép bạn biên dịch trong một giai đoạn và sau đó chỉ sao chép các tạo phẩm kết quả từ giai đoạn xây dựng sang hình ảnh thời gian chạy chỉ có mức tối thiểu cần thiết để chạy ứng dụng. Điều này tránh sự cần thiết phải tối ưu hóa bất kỳ bước xây dựng nào vì chúng không được gửi cùng với hình ảnh kết quả.

FROM debian:9 as build
# still chain update with install to prevent stale cache issues
RUN apt-get update \
 && apt-get install -y \
      a-package \
      wget \
RUN ... # perform any download/compile steps

FROM debian:9-slim as release
COPY --from=build /usr/local/bin/app /usr/local/bin/app
CMD [ "/usr/local/bin/app" ]

Nhiều giai đoạn là lý tưởng với các nhị phân được biên dịch tĩnh mà bạn có thể chạy bằng đầu như hình ảnh cơ sở của mình hoặc chuyển từ môi trường biên dịch như JDK sang thời gian chạy như JRE. Đây là cách dễ nhất để giảm đáng kể kích thước hình ảnh của bạn trong khi vẫn có các bản dựng nhanh. Bạn vẫn có thể thực hiện chuỗi các bước trong giai đoạn phát hành nếu bạn có các bước thay đổi hoặc xóa các tệp được tạo ở các bước trước, nhưng đối với hầu hết các phần, COPYgiai đoạn khác tách biệt giai đoạn phát hành với bất kỳ sự phình to nào trong giai đoạn xây dựng trước đó.


Lưu ý, tôi không khuyên bạn nên xóa hình ảnh vì điều này làm giảm kích thước của một hình ảnh với chi phí loại bỏ việc tái sử dụng lớp. Điều đó có nghĩa là các bản dựng tương lai của cùng một hình ảnh sẽ yêu cầu nhiều lưu lượng đĩa và mạng hơn để gửi các bản cập nhật. Để quay lại ví dụ đầu tiên, squash có thể giảm hình ảnh của bạn từ 2 GB xuống còn 1 GB, nhưng không phải 3 hình ảnh có thể chiếm 3 GB thay vì 2,1 GB.


25

A Dockerfiletạo một lớp mới cho mỗi lệnh trong tệp. Vì các lớp đều tốt, xếp chồng lên nhau - bạn không thể xóa các tệp mà lớp trước đã thêm. Đây là lý do tại sao khi bạn cài đặt các gói, hoặc tải xuống các tệp hoặc tạo các bản dựng trong mỗi lệnh riêng biệt - chúng vẫn còn trong hình ảnh, ngay cả khi trong lớp trong tương lai bạn đã xóa chúng.

Vì vậy, nếu bạn chỉ thay đổi điều này:

RUN apt-get update -y
RUN apt-get install -y wget a-package
# ...
RUN apt-get purge -y wget
RUN rm -r a-build-dir
RUN apt-get purge -y a-package

Về điều này:

RUN apt-get update -y \
    && apt-get install -y wget a-package \
    && mkdir a-build-dir \
    && wget http://some-site/very-big-source-code.tar.gz \
    && tar xzvf very-big-source-code.tar.gz \
    && do-some-compilation \
    && apt-get purge -y wget \
    && cd .. \
    && rm -rf a-build-dir \
    && apt-get purge -y a-package

Bạn sẽ có được một hình ảnh nhỏ hơn nhiều.


Một lựa chọn khác, là để hình ảnh sau khi bạn xây dựng nó. Q: docker --squashCông việc mới như thế nào?


Một lựa chọn khác, là chọn một hình ảnh cơ sở mỏng. Ví dụ: các hình ảnh sử dụng Alpine Linux làm cơ sở thay vì Debian, chỉ mất 10-15mb thay vì 180-250mb. Và đây là trước khi thêm ứng dụng và dữ liệu của riêng bạn. Nhiều hình ảnh cơ sở chính thức trên Docker Hub có phiên bản trên núi cao.


3
2.37so với1.47 GB
030

4

Có lẽ không chính xác một câu trả lời, nhưng đáng để đưa ra các lựa chọn thay thế.

Môi trường sống của đầu bếp đã được tạo ra với ý nghĩ này, tạo ra một gói với tất cả các phụ thuộc cần thiết mà không cần tải hình ảnh phân tán / cơ sở bên ngoài mà bạn không muốn.

Trích xuất những gì quan trọng ở đây, kích thước vùng chứa từ bài đăng trên blog này với một ứng dụng nodejs đơn giản:

michael@ricardo-2:plans_pkg_part_2$ docker images
REPOSITORY           TAG                 IMAGE ID            CREATED             SIZE
mfdii/node-example   latest              36c6568c606b        40 minutes ago      655.9 MB
node                 latest              04c0ca2a8dad        16 hours ago        654.6 MB
mfdii/mytutorialapp  latest              534afd80d74d        2 minutes ago       182.1 MB

mdfii/node-examplelà một hình ảnh docker từ một dockerfile cổ điển trong khi đó mfdii/mytutorialapplà hình ảnh docker được tạo ra với môi trường sống.

Nếu kích thước là mối quan tâm chính của bạn và bạn sẵn sàng thực hiện kế hoạch học tập của các kế hoạch Môi trường sống, thì đây có thể là một giải pháp cho bạn.


0

Người ta cũng có thể sử dụng lặn

docker run --rm -it \
    -v /var/run/docker.sock:/var/run/docker.sock \
    wagoodman/dive:latest <dive arguments...>

để nhận báo cáo về những gì chất thải có thể được loại bỏ khỏi hình ảnh docker để giảm kích thước.


0

Nếu bạn muốn có các lớp phát triển có thể sử dụng lại nhưng giảm mức sử dụng đĩa để phân phối, bạn có thể tạo một "lớp phân phối" được hợp nhất như thế này:

  1. Hãy chắc chắn rằng bạn có một thùng chứa sử dụng hình ảnh của bạn (nếu bạn không có, có thể sử dụng một cái gì đó như docker run IMAGE echo, nếu lệnh echo có sẵn)
  2. Tìm id container (có thể sử dụng docker container ls -l)
  3. Ống docker exportđể docker importtạo lớp hợp nhất (một cái gì đó như docker export 20f192c6530a | docker import - project:merged)

Điều này sẽ giữ các lớp phát triển của bạn xung quanh nhưng cung cấp cho bạn một hình ảnh nhỏ hơn, hợp nhất mà bạn có thể cung cấp.


0

Xây dựng nhiều giai đoạn. Sử dụng hình ảnh có tất cả các thành phần xây dựng của bạn để xây dựng ứng dụng của bạn và hình ảnh thời gian chạy nhẹ hơn. Chỉ sao chép tạo phẩm xây dựng của bạn vào hình ảnh thời gian chạy. Không cần phải xóa bất cứ điều gì.

https://docs.docker.com/develop/develop-images/multistage-build/


0

đơn giản .. docker ps kiểm tra các hình ảnh đang chạy hiện tại..cho ví dụ tập tin đơn giản dưới đây ..

TỪ Ubuntu16

MAINTAINER sreeni (email / tên miền)

CHẠY apt-get cập nhật

CHẠY apt-get install -y nginx

ENTRYPOINT [Ăn / usr / sbin / nginx, Nghi - gặt, da da tắt;

TIẾP 80 (cổng)

tập tin docker đơn giản ...

sử dụng bên dưới lệnh docker

docker chạy -d -p 80:80 - đặt tên máy chủ web ubfox16 (tên hình ảnh) sau đó kiểm tra localhost hoặc địa chỉ ip: 80 (mở trình duyệt và kiểm tra)


1
vui lòng sửa định dạng câu trả lời của bạn ...
Pierre.Vriens
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.