Tại sao hình ảnh container Docker rất lớn?


177

Tôi đã tạo một hình ảnh đơn giản thông qua Dockerfile từ Fedora (ban đầu là 320 MB).

Đã thêm Nano (trình chỉnh sửa nhỏ này có kích thước 1 MB) và kích thước của hình ảnh đã tăng lên 530 MB. Tôi đã thêm Git lên trên đó (30-ish MB), và sau đó tên lửa kích thước hình ảnh của tôi lên 830 MB.

Điều đó có điên không?

Tôi đã cố gắng xuất và nhập container để xóa lịch sử / hình ảnh trung gian. Nỗ lực này đã tiết kiệm tới 25 MB, bây giờ kích thước hình ảnh của tôi là 804 MB. Tôi cũng đã thử chạy nhiều lệnh trên một RUN, nhưng tôi vẫn nhận được 830 MB ban đầu.

Tôi đang nghi ngờ liệu có đáng để sử dụng Docker không. Ý tôi là, tôi hầu như không cài đặt bất cứ thứ gì và tôi đạt hơn 1GB. Nếu tôi sẽ phải thêm một số thứ nghiêm trọng như cơ sở dữ liệu và cứ thế tôi có thể hết dung lượng đĩa.

Bất cứ ai cũng bị kích thước lố bịch của hình ảnh? Làm thế nào để bạn đối phó với nó?

Trừ khi Dockerfile của tôi không chính xác khủng khiếp?

FROM fedora:latest
MAINTAINER Me NotYou <email@dot.com>
RUN yum -y install nano
RUN yum -y install git

nhưng thật khó để tưởng tượng những gì có thể đi sai ở đây.


Bạn đang đo kích thước của container ở đâu và như thế nào? Có yum clean allảnh hưởng gì đến kích thước không?
xeor

2
Hy vọng hình ảnh có kích thước tốt vì nó là sự tích lũy của hình ảnh, hình ảnh gốc và hình ảnh cơ sở. Ngoài ra, yum cài đặt, không chỉ các ứng dụng đã nói, mà cả các phụ thuộc của chúng. docs.docker.com/terms/container
rexposeadas

2
Vâng, "phép đo" của tôi là sự thực thi trong docker imagesđó ở cột cuối cùng có 830 MB. Tôi có thể không biết thực tế kích thước thực tế của hình ảnh của mình là bao nhiêu vì lệnh hình ảnh docker nói rằng 830 MB này là kích thước ảo. Nhưng một lần nữa, kích thước thực tế của hình ảnh là gì?
Zen

Câu trả lời:


118

Như @rexposeadas đã nói, hình ảnh bao gồm tất cả các lớp và mỗi lớp bao gồm tất cả các phụ thuộc cho những gì bạn đã cài đặt. Cũng cần lưu ý rằng các hình ảnh cơ bản (như fedora:latestcó xu hướng rất đơn giản. Bạn có thể ngạc nhiên bởi số lượng phụ thuộc mà phần mềm đã cài đặt của bạn có.

Tôi đã có thể làm cho cài đặt của bạn nhỏ hơn đáng kể bằng cách thêm yum -y clean allvào từng dòng:

FROM fedora:latest
RUN yum -y install nano && yum -y clean all
RUN yum -y install git && yum -y clean all

Điều quan trọng là phải làm điều đó cho mỗi RUN, trước khi lớp được cam kết hoặc nếu không thì xóa không thực sự xóa dữ liệu. Đó là, trong một hệ thống tệp hợp nhất / sao chép khi ghi, việc dọn dẹp ở cuối không thực sự làm giảm việc sử dụng hệ thống tệp vì dữ liệu thực đã được cam kết cho các lớp thấp hơn. Để có được điều này, bạn phải làm sạch ở mỗi lớp.

$ docker history bf5260c6651d
IMAGE               CREATED             CREATED BY                                      SIZE
bf5260c6651d        4 days ago          /bin/sh -c yum -y install git; yum -y clean a   260.7 MB
172743bd5d60        4 days ago          /bin/sh -c yum -y install nano; yum -y clean    12.39 MB
3f2fed40e4b0        2 weeks ago         /bin/sh -c #(nop) ADD file:cee1a4fcfcd00d18da   372.7 MB
fd241224e9cf        2 weeks ago         /bin/sh -c #(nop) MAINTAINER Lokesh Mandvekar   0 B
511136ea3c5a        12 months ago                                                       0 B

1
Cảm ơn bạn đã nỗ lực điều tra vụ án, và vâng tôi đã có thể giảm kích thước hình ảnh của mình xuống còn khoảng 635 MB (đây là giá trị được trình bày dưới dạng kích thước hình ảnh ảo sau khi thực hiện docker images). Có thể loại bỏ / xóa / phá hủy các lớp cũ? Để rõ hơn .
Zen

(Quá dài cho 1 bình luận) Trừ khi kích thước hình ảnh ảo không liên quan gì đến kích thước thực tế của hình ảnh trên ổ cứng? Nếu đây là trường hợp, thì làm thế nào / ở đâu để kiểm tra kích thước thực tế của hình ảnh của tôi?
Zen

Bạn có thể docker exportvà sau đó docker importmột lần nữa. Điều đó sẽ làm phẳng các lớp. Tôi không nghĩ rằng nó sẽ làm giảm kích thước, nhưng tôi có thể sai.
Andy

10
Vâng nhưng xuất khẩu không tiết kiệm nhiều. Tuy nhiên, tôi đã có thể đọc qua web rằng những gì tôi có thể quan sát trong docker là kích thước hình ảnh ảo. Kích thước thực tế trên ổ cứng dường như là bí ẩn đối với tôi vì đối với thông tin chính thức docker ps -scho thấy kích thước thật trên ổ cứng mà trong trường hợp của tôi là -1B. Nghe có vẻ hợp lý, trừ 1 Byte . Tôi đã đạt được một số dung lượng trên ổ cứng ... có vẻ hợp pháp.
Zen

@Zen Xin lỗi tôi không theo dõi. Vậy kích thước ảo và kích thước đĩa là 2 thứ khác nhau? Chính xác những gì kích thước ảo đo lường?
Jason

63

Docker hình ảnh không lớn, bạn chỉ đang xây dựng hình ảnh lớn.

Các scratchhình ảnh là 0B và bạn có thể sử dụng để đóng gói lên mã của bạn nếu bạn có thể biên dịch mã của bạn thành một nhị phân tĩnh. Ví dụ: bạn có thể biên dịch chương trình Go của mình và gói nó lên trên cùngscratch để tạo ra một hình ảnh hoàn toàn có thể sử dụng được dưới 5MB.

Điều quan trọng là không sử dụng hình ảnh Docker chính thức, chúng quá lớn. Scratch cũng không thực tế lắm nên tôi khuyên bạn nên sử dụng Alpine Linux làm hình ảnh cơ bản. Nó là ~ 5 MB, sau đó chỉ thêm những gì cần thiết cho ứng dụng của bạn. Bài đăng này về Microcontainers chỉ cho bạn cách xây dựng những hình ảnh rất nhỏ dựa trên cơ sở Alps.

CẬP NHẬT: hình ảnh Docker chính thức dựa trên alpine bây giờ vì vậy chúng rất tốt để sử dụng ngay bây giờ.


2
Giải pháp tuyệt vời!, Điều quan trọng là phải dừng lãng phí và giữ an toàn hơn ---> ít mã hơn -> ít lo lắng hơn.
Ran Davidovitz

1
Rất may, các hình ảnh chính thức của Docker cũng đang chuyển sang sử dụng cơ sở Alps, do đó, ngày càng nhiều bạn có thể sử dụng các hình ảnh thông thường thay vì phụ thuộc vào các phiên bản của iron.io. Xem brianchristner.io/docker-is-moving-to-alpine-linux
Martijn Heemels

@Travis R, liên kết của bạn để đăng bài về các nhà vi điều khiển dường như đã chuyển đi nơi khác. Là này trong bài viết bạn có nghĩa là để liên kết?
Alexander F.

@AlexanderF. Đã sửa lỗi liên kết, cảm ơn đã cho tôi biết.
Travis Reeder

28

Dưới đây là một số điều bạn có thể làm :

  • Tránh nhiều RUNlệnh nơi bạn có thể. Đặt càng nhiều càng tốt vào một RUNlệnh (sử dụng &&)
  • dọn dẹp các công cụ không cần thiết như wget hoặc git (mà bạn chỉ cần tải xuống hoặc xây dựng công cụ, nhưng không chạy quy trình của bạn)

Với cả hai VÀ các đề xuất từ ​​@Andy và @michau, tôi đã có thể thay đổi kích thước hình ảnh nodejs của mình từ 1.062 GB thành 542 MB.

Chỉnh sửa: Một điều quan trọng hơn: "Tôi phải mất một thời gian để thực sự hiểu rằng mỗi lệnh Dockerfile tạo ra một thùng chứa mới với deltas. [...] Không thành vấn đề nếu bạn rm -rf các tệp trong lệnh sau; chúng tiếp tục tồn tại trong một số container lớp trung gian. " Vì vậy, bây giờ tôi quản lý để đặt apt-get install, wget, npm install(với phụ thuộc git) và apt-get removevào một đơn RUNlệnh, vì vậy bây giờ hình ảnh của tôi chỉ có 438 MB.

Chỉnh sửa 29/06/17

Với Docker v17.06, có một tính năng mới cho Dockerfiles: Bạn có thể có nhiều FROMcâu lệnh bên trong một Dockerfile và chỉ những thứ cuối cùng FROMmới có trong hình ảnh Docker cuối cùng của bạn. Điều này rất hữu ích để giảm kích thước hình ảnh, ví dụ:

FROM nodejs as builder
WORKDIR /var/my-project
RUN apt-get install ruby python git openssh gcc && \
    git clone my-project . && \
    npm install

FROM nodejs
COPY --from=builder /var/my-project /var/my-project

Sẽ dẫn đến một hình ảnh chỉ có hình ảnh cơ sở của nodejs cộng với nội dung từ / var / my-project từ các bước đầu tiên - nhưng không có ruby, python, git, openssh và gcc!


22

Vâng, những kích thước đó là vô lý, và tôi thực sự không biết tại sao rất ít người nhận thấy điều đó.

Tôi đã tạo một hình ảnh Ubuntu thực sự tối thiểu (không giống như các hình ảnh được gọi là "tối thiểu" khác). Nó được gọi textlab/ubuntu-essentialvà có 60 MB.

FROM textlab/ubuntu-essential
RUN apt-get update && apt-get -y install nano

Hình ảnh trên là 82 MB sau khi cài đặt nano.

FROM textlab/ubuntu-essential
RUN apt-get update && apt-get -y install nano git

Git có nhiều điều kiện tiên quyết hơn, vì vậy hình ảnh sẽ lớn hơn, khoảng 192 MB. Đó vẫn là kích thước ban đầu của hầu hết các hình ảnh.

Bạn cũng có thể xem kịch bản tôi đã viết để tạo hình ảnh Ubuntu tối thiểu cho Docker . Bạn có thể có thể thích ứng nó với Fedora, nhưng tôi không chắc bạn sẽ có thể gỡ cài đặt bao nhiêu.


13

Sau đây đã giúp tôi rất nhiều:

Sau khi loại bỏ các gói không sử dụng (ví dụ: giải phóng 1200 mb) trong thùng chứa của tôi, tôi đã thực hiện như sau:

  1. xuất docker [containerID] -o chứaername.tar
  2. nhập docker -m "thông báo cam kết tại đây" chứa tên người dùng

Các lớp được làm phẳng. Kích thước của hình ảnh mới sẽ nhỏ hơn vì tôi đã xóa các gói khỏi vùng chứa như đã nêu ở trên.

Điều này đã mất rất nhiều thời gian để hiểu điều này và đó là lý do tại sao tôi đã thêm nhận xét của mình.


Bạn có thể kết hợp cả hai bước thành một bước duy nhấtdocker export <CONTAINER ID> | docker import - some-image-name:latest
Anuj Kumar

8

Để thực hành tốt nhất, bạn nên thực hiện một lệnh RUN duy nhất, bởi vì mỗi lệnh RUN trong Dockerfile ghi một lớp mới trong hình ảnh và mỗi lớp yêu cầu thêm không gian trên đĩa. Để giữ cho các lớp số ở mức tối thiểu, mọi thao tác tệp như cài đặt, di chuyển, giải nén, xóa, v.v., lý tưởng nhất phải được thực hiện theo một lệnh RUN duy nhất

FROM fedora:latest
RUN yum -y install nano git && yum -y clean all

4

Docker Squash là một giải pháp thực sự tốt cho việc này. bạn có thể $packagemanager cleanở bước cuối cùng thay vì trong mỗi dòng và sau đó chỉ cần chạy một docker squash để loại bỏ tất cả các lớp.

https://github.com/jwilder/docker-squash


0

Có hệ thống lớp khá đáng ngạc nhiên. Nếu bạn có một hình ảnh cơ sở và bạn tăng nó bằng cách làm như sau:

# Test
#
# VERSION       1

# use the centos base image provided by dotCloud
FROM centos7/wildfly
MAINTAINER JohnDo 

# Build it with: docker build -t "centos7/test" test/

# Change user into root
USER root

# Extract weblogic
RUN rm -rf /tmp/* \
    && rm -rf /wildfly/* 

Hình ảnh có cùng kích thước. Điều đó về cơ bản có nghĩa là, bạn phải quản lý để đưa vào các bước RUN của mình rất nhiều trích xuất, cài đặt và dọn dẹp ma thuật để làm cho hình ảnh nhỏ như phần mềm được cài đặt.

Điều này làm cho cuộc sống khó khăn hơn nhiều ...

DockerBuild thiếu các bước CHẠY mà không có cam kết.

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.