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.
yum clean all
ma wpływ na rozmiar?docker images
któ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?Odpowiedzi:
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 jak
fedora: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 all
do każdej linii: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ę.
źródło
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 .docker export
a potemdocker import
znowu. To spłaszczyłoby warstwy. Nie sądzę, żeby to zmniejszyło rozmiar, ale mogę się mylić.docker ps -s
pokazuje rzeczywisty rozmiar dysku twardego, który w moim przypadku był-1B
. Brzmi rozsądnie, minus 1 bajt . Zyskałem trochę miejsca na dysku twardym ...Obrazy Dockera nie są duże, po prostu tworzysz duże obrazy.
scratch
Obraz 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ć.
źródło
Oto kilka innych rzeczy, które możesz zrobić :
RUN
poleceń, jeśli możesz. Umieść jak najwięcej w jednymRUN
poleceniu (używając&&
)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) iapt-get remove
na 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
FROM
instrukcji w jednym pliku Dockerfile, a naFROM
ostatecznym obrazie Dockera będą znajdować się tylko rzeczy z ostatniego . Jest to przydatne do zmniejszenia rozmiaru obrazu, na przykład: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!
źródło
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-essential
i ma 60 MB.Powyższy obraz ma 82 MB po zainstalowaniu nano.
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ć.
źródło
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:
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.
źródło
docker export <CONTAINER ID> | docker import - some-image-name:latest
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
źródło
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
źródło
Tak, system warstw jest dość zaskakujący. Jeśli masz obraz podstawowy i zwiększasz go, wykonując następujące czynności:
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.
źródło