[nawiązanie do amerykańskiej bajki dla dzieci „Mały silnik, który mógł” – ok. uliczka]*
Jak automatycznie tworzyć małe obrazy Dockera dla swoich potrzeb
Niezwykła obsesja
Przez ostatnie kilka miesięcy miałem obsesję na punkcie tego, jak mały może być obraz Dockera, a aplikacja nadal działa?
Rozumiem, pomysł jest dziwny.
Zanim przejdę do szczegółów i zawiłości technicznych, chciałbym wyjaśnić, dlaczego ten problem tak mnie niepokoił, a jak dotyczy Ciebie.
Dlaczego rozmiar ma znaczenie
Zmniejszając zawartość obrazu Dockera, zmniejszamy w ten sposób listę luk. Dodatkowo sprawiamy, że obrazy są czystsze, ponieważ zawierają tylko to, co jest potrzebne do uruchomienia aplikacji.
Jest jeszcze jedna mała zaleta - obrazy pobierają się nieco szybciej, ale moim zdaniem nie jest to aż tak istotne.
Uwaga: jeśli martwisz się rozmiarem, modele Alpine same w sobie są małe i prawdopodobnie będą na Ciebie pasować.
Obrazy bez Distroless
pip
и apt
nie będzie działać:
FROM gcr.io/distroless/python3
RUN pip3 install numpy
Dockerfile przy użyciu obrazu Python 3 bez dystrybucji
Sending build context to Docker daemon 2.048kB
Step 1/2 : FROM gcr.io/distroless/python3
---> 556d570d5c53
Step 2/2 : RUN pip3 install numpy
---> Running in dbfe5623f125
/bin/sh: 1: pip3: not found
Pipa nie ma na obrazku
Zwykle problem ten rozwiązuje się poprzez wieloetapową kompilację:
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/
Montaż wieloetapowy
Rezultatem jest obraz o rozmiarze 130MB. Nieźle! Dla porównania: domyślny obraz Pythona waży 929 MB, a „cieńszy” (3,7-slim
) - 179 MB, obraz alpejski (3,7-alpine
) wynosi 98,6 MB, podczas gdy podstawowy obraz Distroless użyty w przykładzie to 50,9 MB.
Warto zaznaczyć, że w poprzednim przykładzie kopiujemy cały katalog /usr/local/lib/python3.7/site-packages
, które mogą zawierać zależności, których nie potrzebujemy. Chociaż jasne jest, że różnica wielkości wszystkich istniejących obrazów podstawowych Pythona jest różna.
W chwili pisania tego tekstu Google distroless nie obsługuje wielu obrazów: Java i Python są wciąż w fazie eksperymentalnej, a Python istnieje tylko w wersjach 2,7 i 3,5.
Malutkie obrazy
Wracając do mojej obsesji na punkcie tworzenia małych obrazów.
Ogólnie chciałem zobaczyć, jak konstruowane są obrazy distroless. Projekt distroless wykorzystuje narzędzie do kompilacji Google bazel
. Jednak instalacja Bazela i napisanie własnych obrazów wymagało dużo pracy (i szczerze mówiąc, wymyślanie koła na nowo jest zabawne i edukacyjne). Chciałem uprościć tworzenie mniejszych obrazów: sam akt tworzenia obrazu powinien być niezwykle prosty, banalny. Żeby nie było dla Ciebie żadnych plików konfiguracyjnych, tylko jedna linijka w konsoli: просто собрать образ для <приложение>
.
Jeśli więc chcesz tworzyć własne obrazy, wiedz: istnieje taki unikalny obraz dokera, scratch
. Scratch to „pusty” obraz, nie ma w nim żadnych plików, chociaż domyślnie waży - wow! - 77 bajtów.
FROM scratch
Zdrap obraz
Ideą obrazu podstawowego jest to, że możesz skopiować na niego dowolne zależności z komputera hosta i albo użyć ich w pliku Dockerfile (to jakby skopiować je do apt
i zainstaluj od zera) lub później, gdy obraz Dockera zostanie zmaterializowany. Pozwala to na pełną kontrolę zawartości kontenera Docker, a co za tym idzie pełną kontrolę nad rozmiarem obrazu.
Teraz musimy jakoś zebrać te zależności. Istniejące narzędzia, takie jak apt
umożliwiają pobieranie pakietów, ale są one powiązane z bieżącą maszyną i w końcu nie obsługują systemu Windows ani MacOS.
Postanowiłem więc zbudować własne narzędzie, które automatycznie zbuduje obraz bazowy o możliwie najmniejszym rozmiarze, a także uruchomi dowolną aplikację. Użyłem pakietów Ubuntu/Debian, dokonałem selekcji (pobierając pakiety bezpośrednio z repozytoriów) i rekurencyjnie znalazłem ich zależności. Program miał automatycznie pobierać najnowszą stabilną wersję pakietu, maksymalnie minimalizując zagrożenia bezpieczeństwa.
Nazwałem to narzędzie fetchy
, bo on... znajduje i przynosi... to, co jest potrzebne [z angielskiego „przynieś”, „przynieś” – ok. uliczka] Narzędzie działa poprzez interfejs wiersza poleceń, ale jednocześnie oferuje API.
Aby złożyć obraz za pomocą fetchy
(tym razem weźmy obraz w języku Python), wystarczy użyć interfejsu CLI w następujący sposób: fetchy dockerize python
. Możesz zostać poproszony o podanie docelowego systemu operacyjnego i nazwy kodowej, ponieważ fetchy
obecnie używa tylko pakietów opartych na Debianie i Ubuntu.
Teraz możesz wybrać, które zależności nie są w ogóle potrzebne (w naszym kontekście) i je wykluczyć. Na przykład Python zależy od Perla, chociaż działa dobrze bez zainstalowanego Perla.
wyniki
Obraz Pythona utworzony za pomocą polecenia fetchy dockerize python3.5
waży tylko 35 MB (jestem więcej niż pewien, że w przyszłości można go uczynić jeszcze lżejszym). Okazuje się, że udało nam się ogolić kolejne 15 WW z obrazu distroless.
Możesz zobaczyć wszystkie zebrane do tej pory obrazy
Projekt -
Jeśli brakuje Ci funkcji, po prostu utwórz wniosek - chętnie pomogę :) Co więcej, obecnie pracuję nad integracją innych menedżerów pakietów z fetchy, aby nie było potrzeby wieloetapowej kompilacji.
Źródło: www.habr.com