Małe obrazy Dockera, które uwierzyły w siebie*

[nawiązanie do amerykańskiej bajki dla dzieci „Mały silnik, który mógł” – ok. uliczka]*

Małe obrazy Dockera, które uwierzyły w siebie*

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

Projekt Distroless oferuje wybór podstawowych obrazów „distroless”, nie zawierają one menedżerów pakietów, powłok i innych narzędzi, które zwykle widzisz w wierszu poleceń. W rezultacie użyj menedżerów pakietów, takich jak 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 tutaj.

Projekt - tutaj.

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

Dodaj komentarz