[nawiązanie do amerykańskiej bajki dla dzieci „Mały pociąg, który mógł” („The Little Engine That Could”) — przyp.red.]

Jak automatycznie tworzyć małe obrazy dockerowe dla swoich potrzeb
Dziwna obsesja
Ostatnie kilka miesięcy byłem obsesyjnie zainteresowany jedną myślą: jak bardzo można zmniejszyć obraz Docker, aby aplikacja nadal działała?
Rozumiem, że to dziwna idea.
Zanim zagłębię się w szczegóły i techniczne zawirowania, chciałbym wyjaśnić, co tak bardzo mnie zainteresowało i jak to dotyczy Ciebie.
Dlaczego rozmiar ma znaczenie
Zmniejszając zawartość obrazu Docker, jednocześnie zmniejszamy listę podatności. Dodatkowo, nasze obrazy stają się czystsze, ponieważ zawierają tylko to, co potrzebne do uruchomienia aplikacji.
Jest jeszcze jedna mała zaleta — obrazy ściągają się trochę szybciej, ale według mnie to nie jest aż tak istotne.
Zwróć uwagę: Jeśli rozmiar jest dla Ciebie ważny, obrazy Alpine są same w sobie małe i z pewnością będą odpowiednie.
Obrazy Distroless
oferuje zestaw podstawowych obrazów „distroless”, które nie zawierają menedżerów pakietów, powłok i innych narzędzi, które zwykle widzisz w terminalu. W rezultacie nie można użyć menedżerów pakietów takich jak pip i apt tak więc:
FROM gcr.io/distroless/python3
RUN pip3 install numpyDockerfile, korzystający z obrazu distroless Python 3
Wysyłanie kontekstu budowy do demona Docker 2.048kB
Krok 1/2 : FROM gcr.io/distroless/python3
---> 556d570d5c53
Krok 2/2 : RUN pip3 install numpy
---> Uruchamianie w dbfe5623f125
/bin/sh: 1: pip3: nie znalezionoPipa w obrazie nie ma
Zazwyczaj ta sytuacja rozwiązywana jest przy pomocy budowy wieloetapowej:
FROM python:3 as builder
RUN pip3 install numpy
FROM gcr.io/distroless/python3
COPY --from=builder /usr/local/lib/python3.7/site-packages /usr/local/lib/python3.5/Wieloetapowa budowa
W rezultacie otrzymujemy obraz o rozmiarze 130MB. Nie tak źle! Dla porównania: domyślny obraz Python waży 929MB, a 'zredukowany' (3,7-slim) — 179MB, obraz alpine (3,7-alpine) — 98,6MB, podczas gdy podstawowy obraz distroless użyty w przykładzie to 50,9MB.
Można słusznie zauważyć, że w poprzednim przykładzie kopiujemy cały katalog /usr/local/lib/python3.7/site-packages, w którym mogą znajdować się niechciane zależności. Chociaż jasne jest, że różnice w rozmiarze wszystkich istniejących podstawowych obrazów Python są zróżnicowane.
W momencie pisania tych słów Google distroless nie obsługuje jeszcze tak wielu obrazów: Java i Python — wciąż na etapie eksperymentu, a Python istnieje tylko dla wersji 2.7 i 3.5.
Małe obrazy
Wróćmy do mojego obsesji na punkcie tworzenia małych obrazów.
Ogólnie chciałem zobaczyć, jak są zbudowane obrazy distroless. Projekt distroless wykorzystuje narzędzie do budowy od Google’a. bazel. Jednak żeby zainstalować Bazel i stworzyć własne obrazy, musiałem się napracować (a jeśli być do końca szczerym, powtórnie wynajdować koło — to jest zabawne i pouczające). Chciałem uprościć tworzenie zmniejszonych obrazów: akt tworzenia obrazu powinien być maksymalnie prosty, banalny. Żadnych plików konfiguracyjnych, tylko jedna linia w konsoli: po prostu zbudować obraz dla.
Zatem, jeśli chcecie tworzyć własne obrazy, to pamiętajcie: jest taki unikalny obraz docker, scratch. Scratch to "pusty" obraz, nie ma w nim plików, chociaż domyślnie waży — o matko! — 77 bajtów.
FROM scratchObraz scratch
Idea obrazu scratch polega na tym, że można skopiować do niego wszelkie zależności z maszyny hosta i albo używać ich w Dockerfile (to tak, jakby je skopiować i zainstalować od podstaw), albo później, gdy obraz Docker zostanie zmaterializowany. Pozwala to całkowicie kontrolować zawartość kontenera Docker, a tym samym całkowicie kontrolować rozmiar obrazu. apt A teraz musimy jakoś zebrać te zależności. Istniejące narzędzia, takie jak
pozwalają pobierać pakiety, ale są przypisane do aktualnej maszyny i ostatecznie nie wspierają Windows ani MacOS. apt I tak postanowiłem stworzyć własne narzędzie, które automatycznie tworzyłoby bazowy obraz o jak najmniejszym rozmiarze i żeby ten jeszcze uruchamiał jakąkolwiek aplikację. Użyłem pakietów Ubuntu/Debian, pobierałem (otrzymując pakiety bezpośrednio z repozytoriów) i rekursywnie znajdowałem ich zależności. Program miał automatycznie pobierać najnowszą stabilną wersję pakietu, maksymalnie minimalizując ryzyko dla bezpieczeństwa.
Narzędzie nazwałem
fetchy , ponieważ... znajduje i przynosi... to, co potrzebne [od ang. „fetch”, „przynosić” — przyp. tł.]. Narzędzie działa przez interfejs wiersza poleceń, ale jednocześnie oferuje też API.Aby zbudować obraz za pomocą
(weźmy tym razem obraz Python), wystarczy użyć CLI w ten sposób: , ponieważ... znajduje i przynosi... to, co potrzebne [ fetchy dockerize python . Mogą poprosić o docelowy system operacyjny i nazwę kodową, ponieważna razie używa tylko pakietów opartych na Debianie i Ubuntu. , ponieważ... znajduje i przynosi... to, co potrzebne [ na razie używa tylko pakietów opartych na Debianie i Ubuntu.
Teraz można wybierać, które zależności są zupełnie niepotrzebne (w naszym kontekście) i je wykluczyć. Na przykład, Python zależy od Perla, chociaż wspaniale działa bez zainstalowanego Perla.
Wyniki
Obraz Pythona, stworzony za pomocą polecenia fetchy dockerize python3.5 waży tylko 35 MB (jestem więcej niż pewny, że w przyszłości można go jeszcze bardziej odchudzić). Okazuje się, że udało się 'zredukować' jeszcze 15 MB z obrazu distroless.
Wszystkie zbudowane jak dotąd obrazy można zobaczyć .
Projekt — .
Jeśli brakuje Ci funkcji, po prostu zgłoś zapotrzebowanie — z przyjemnością pomogę 🙂 Co więcej, aktualnie pracuję nad integracją w fetchy innych menedżerów pakietów, aby uniknąć konieczności wieloetapowych budów.
Źródło: habr.com
