Dlaczego obrazy kontenerów platformy Docker są tak duże?

177

Zrobiłem prosty obraz za pomocą Dockerfile z Fedory (początkowo 320 MB).

Dodano Nano (ten mały edytor o rozmiarze 1 MB), a rozmiar obrazu wzrósł do 530 MB. Dodałem do tego Gita (30-ish MB), a potem moje rakiety o rozmiarze obrazu do 830 MB.

Czy to nie jest szalone?

Próbowałem wyeksportować i zaimportować kontener, aby usunąć historię / obrazy pośrednie. Ten wysiłek zaoszczędził do 25 MB, teraz mój rozmiar obrazu to 804 MB. Próbowałem też uruchomić wiele poleceń na jednym RUN, ale nadal otrzymuję te same początkowe 830 MB.

Mam wątpliwości, czy w ogóle warto używać Dockera. Chodzi mi o to, że ledwo coś zainstalowałem i przekraczam 1 GB. Jeśli będę musiał dodać jakieś poważne rzeczy, takie jak baza danych i tak dalej, może zabraknąć mi miejsca na dysku.

Ktoś cierpi na absurdalne rozmiary obrazów? Jak sobie z tym radzisz?

Chyba że mój plik Dockerfile jest strasznie niepoprawny?

FROM fedora:latest
MAINTAINER Me NotYou <[email protected]>
RUN yum -y install nano
RUN yum -y install git

ale trudno sobie wyobrazić, co może tu pójść nie tak.

Zen
źródło
Gdzie i jak mierzysz rozmiar swojego pojemnika? Czy yum clean allma wpływ na rozmiar?
xeor
2
Oczekuj, że obrazy będą miały dobry rozmiar, ponieważ jest to nagromadzenie jego obrazu, obrazu (-ów) nadrzędnego (-ych) i obrazu podstawowego. Ponadto yum instaluje nie tylko wspomniane aplikacje, ale także ich zależności. docs.docker.com/terms/container
rexposadas
2
Cóż, moim „pomiarem” jest wykonanie, docker imagesktórego wykonanie w ostatniej kolumnie wskazuje potężne 830MB. Mogę nie wiedzieć, jaki jest rzeczywisty rozmiar mojego obrazu, ponieważ polecenie docker images stwierdza, że ​​to 830 MB to rozmiar wirtualny. Ale z drugiej strony, jaki jest rzeczywisty rozmiar obrazu?
Zen

Odpowiedzi:

118

Jak powiedział @rexposadas, obrazy obejmują wszystkie warstwy, a każda warstwa zawiera wszystkie zależności od tego, co zainstalowałeś. Ważne jest również, aby pamiętać, że obrazy podstawowe (takie jakfedora:latest są bardzo proste. Możesz być zaskoczony liczbą zależności, które ma zainstalowane oprogramowanie.

Udało mi się znacznie zmniejszyć twoją instalację, dodając yum -y clean alldo każdej linii:

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

Ważne jest, aby zrobić to dla każdego RUN, zanim warstwa zostanie zatwierdzona, w przeciwnym razie usuwanie nie usuwa danych. Oznacza to, że w systemie plików typu union / copy-on-write czyszczenie na końcu tak naprawdę nie zmniejsza wykorzystania systemu plików, ponieważ rzeczywiste dane są już przypisane do niższych warstw. Aby obejść ten problem, należy czyścić każdą warstwę.

$ 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
Andy
źródło
1
Dziękuję za wysiłek włożony w zbadanie sprawy i tak, udało mi się zmniejszyć rozmiar mojego obrazu do około 635 MB (jest to wartość prezentowana jako rozmiar obrazu wirtualnego po wykonaniu docker images). Czy można usunąć / usunąć / zniszczyć te stare warstwy? Mówiąc dokładniej: chciałbym całkowicie usunąć (na podstawie twojego przykładu) obrazy: 172743bd5d60, 3f2fed40e4b0, fd241224e9cf, 511136ea3c5a z historii, aby rozmiar mojego wirtualnego obrazu był mniej więcej taki sam jak rozmiar ostatecznego obrazu, tutaj ~ 260MB .
Zen
(Za długi na 1 komentarz) Chyba że rozmiar obrazu wirtualnego nie ma nic wspólnego z rzeczywistym rozmiarem obrazu na dysku twardym? Jeśli tak jest, to jak / gdzie sprawdzić rzeczywisty rozmiar moich obrazów?
Zen
Możesz, docker exporta potem docker importznowu. To spłaszczyłoby warstwy. Nie sądzę, żeby to zmniejszyło rozmiar, ale mogę się mylić.
Andy
10
Tak, ale eksport niewiele oszczędza. Mimo to udało mi się przeczytać w sieci, że to, co widzę w dockerze, to wirtualny rozmiar obrazu. Rzeczywisty rozmiar dysku twardego wydaje mi się tajemniczy, ponieważ w odniesieniu do oficjalnych informacji docker ps -spokazuje rzeczywisty rozmiar dysku twardego, który w moim przypadku był -1B. Brzmi rozsądnie, minus 1 bajt . Zyskałem trochę miejsca na dysku twardym ...
Zen
@Zen Przepraszamy, nie śledzę. Czyli rozmiar wirtualny i rozmiar dysku to dwie różne rzeczy? Co dokładnie mierzy rozmiar wirtualny?
Jason
63

Obrazy Dockera nie są duże, po prostu tworzysz duże obrazy.

scratchObraz jest 0B i można używać, aby spakować swój kod, jeśli można skompilować kod do statycznego binarny. Na przykład możesz skompilować swój program Go i spakować go na wierzch,scratch aby utworzyć w pełni użyteczny obraz o rozmiarze mniejszym niż 5 MB.

Najważniejsze jest, aby nie używać oficjalnych obrazów Dockera, są one zbyt duże. Scratch też nie jest aż tak praktyczny, więc polecam używanie Alpine Linux jako obrazu podstawowego. Jest to ~ 5 MB, a następnie dodaj tylko to, co jest wymagane dla Twojej aplikacji. Ten post o mikrokontenerach pokazuje, jak budować bardzo małe obrazy w oparciu o Alpine.

AKTUALIZACJA: oficjalne obrazy Dockera są teraz oparte na Alpine, więc można ich teraz używać.

Travis Reeder
źródło
2
Świetne rozwiązanie !, Tak ważne jest, aby zatrzymać marnotrawstwo i zachować większe bezpieczeństwo ---> mniej kodu -> mniej zmartwień.
Ran Davidovitz
1
Na szczęście oficjalne obrazy Dockera również przenoszą się do korzystania z bazy Alpine, więc coraz częściej możesz używać zwykłych obrazów zamiast polegać na wersjach iron.io. Zobacz brianchristner.io/docker-is-moving-to-alpine-linux
Martijn Heemels
@Travis R, Twój link do posta o mikrokontenerach wydaje się być przeniesiony gdzie indziej. Czy to jest post, który chciałeś połączyć?
Alexander F.
@AlexanderF. Naprawione linki, dzięki za poinformowanie mnie.
Travis Reeder
28

Oto kilka innych rzeczy, które możesz zrobić :

  • Unikaj wielu RUNpoleceń, jeśli możesz. Umieść jak najwięcej w jednym RUNpoleceniu (używając&& )
  • wyczyść niepotrzebne narzędzia, takie jak wget lub git (których potrzebujesz tylko do pobierania lub budowania rzeczy, ale nie do uruchamiania procesu)

Dzięki tym i zaleceniom @Andy i @michau byłem w stanie zmienić rozmiar mojego obrazu nodejs z 1,062 GB na 542 MB.

Edycja: Jeszcze jedna ważna rzecz: „Zajęło mi trochę czasu, zanim naprawdę zrozumiałem, że każde polecenie Dockerfile tworzy nowy kontener z deltami. [...] Nie ma znaczenia, czy rm -rf pliki w późniejszym poleceniu; nadal istnieją w pewnym kontenerze warstwy pośredniej. " Więc teraz udało mi się położyć apt-get install, wget, npm install(z zależnościami git) i apt-get removena pojedynczymRUN dowództwem, więc teraz mój obraz ma tylko 438 MB.

Edycja 29/06/17

Wraz z wersją Docker 17.06 pojawiły się nowe funkcje dla plików Dockerfiles: możesz mieć wiele FROMinstrukcji w jednym pliku Dockerfile, a na FROMostatecznym obrazie Dockera będą znajdować się tylko rzeczy z ostatniego . Jest to przydatne do zmniejszenia rozmiaru obrazu, na przykład:

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

W rezultacie obraz będzie miał tylko obraz podstawowy nodejs oraz zawartość z / var / my-project z pierwszych kroków - ale bez ruby, python, git, openssh i gcc!

Munchkin
źródło
22

Tak, te rozmiary są śmieszne i naprawdę nie mam pojęcia, dlaczego tak niewielu ludzi to zauważa.

Zrobiłem obraz Ubuntu, który jest faktycznie minimalny (w przeciwieństwie do innych tak zwanych „minimalnych” obrazów). Nazywa się textlab/ubuntu-essentiali ma 60 MB.

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

Powyższy obraz ma 82 MB po zainstalowaniu nano.

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

Git ma o wiele więcej wymagań wstępnych, więc obraz staje się większy, około 192 MB. To wciąż mniej niż początkowy rozmiar większości obrazów.

Możesz również rzucić okiem na skrypt, który napisałem, aby stworzyć minimalny obraz Ubuntu dla Dockera . Być może możesz dostosować go do Fedory, ale nie jestem pewien, ile uda ci się odinstalować.

michau
źródło
13

Bardzo mi pomogły:

Po usunięciu nieużywanych opakowań (np. Redis 1200 mb zwolnionych) w moim kontenerze, wykonałem następujące czynności:

  1. docker export [ID kontenera] -o nazwa_zbiornika.tar
  2. docker import -m "komunikat o zatwierdzeniu tutaj" nazwa_zbiornika.tar nazwa_obrazu: znacznik

Warstwy ulegają spłaszczeniu. Rozmiar nowego obrazu będzie mniejszy, ponieważ usunąłem pakiety z kontenera, jak wspomniano powyżej.

Zrozumienie tego zajęło dużo czasu i dlatego dodałem swój komentarz.

Jeffrey Schmitz
źródło
Możesz połączyć oba kroki w jedendocker export <CONTAINER ID> | docker import - some-image-name:latest
Anuj Kumar
8

Aby uzyskać najlepszą praktykę, należy wykonać pojedyncze polecenie RUN, ponieważ każda instrukcja RUN w pliku Dockerfile zapisuje nową warstwę w obrazie, a każda warstwa wymaga dodatkowego miejsca na dysku. Aby ograniczyć liczbę warstw do minimum, wszelkie operacje na plikach, takie jak instalacja, przenoszenie, wyodrębnianie, usuwanie itp., Powinny być idealnie wykonywane w ramach jednej instrukcji RUN

FROM fedora:latest
RUN yum -y install nano git && yum -y clean all
tmz83
źródło
4

Docker Squash to naprawdę fajne rozwiązanie. możesz$packagemanager clean w ostatnim kroku zamiast w każdej linii, a następnie po prostu uruchomić docker squash, aby pozbyć się wszystkich warstw.

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

jeremyjjbrown
źródło
0

Tak, system warstw jest dość zaskakujący. Jeśli masz obraz podstawowy i zwiększasz go, wykonując następujące czynności:

# 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/* 

Obraz ma dokładnie ten sam rozmiar. Zasadniczo oznacza to, że musisz włożyć w swoje kroki RUN wiele magii wyodrębniania, instalowania i czyszczenia, aby obrazy były tak małe, jak zainstalowane oprogramowanie.

To znacznie utrudnia życie ...

W dockerBuild brakuje kroków RUN bez zatwierdzenia.

99Sono
źródło