Winzige Docker-Images, die an sich glaubten*

[Anspielung auf das amerikanische Kindermärchen „The Little Engine That Could“ – ca. Fahrbahn]*

Winzige Docker-Images, die an sich glaubten*

So erstellen Sie automatisch winzige Docker-Images für Ihre Anforderungen

Ungewöhnliche Besessenheit

In den letzten paar Monaten war ich besessen davon, wie klein ein Docker-Image sein kann und wie die Anwendung trotzdem ausgeführt werden kann.

Ich verstehe, die Idee ist seltsam.

Bevor ich auf die Details und technischen Details eingehe, möchte ich erklären, warum mich dieses Problem so sehr beschäftigt hat und inwiefern es Sie betrifft.

Warum Größe wichtig ist

Indem wir den Inhalt des Docker-Images reduzieren, reduzieren wir dadurch die Liste der Schwachstellen. Darüber hinaus machen wir die Bilder sauberer, da sie nur das enthalten, was zum Ausführen von Anwendungen erforderlich ist.

Es gibt noch einen kleinen Vorteil: Bilder werden etwas schneller heruntergeladen, aber meiner Meinung nach ist das nicht so wichtig.

Bitte beachten Sie: Wenn Sie Bedenken hinsichtlich der Größe haben, fallen die Alpine-Looks selbst klein aus und werden Ihnen wahrscheinlich passen.

Distroless-Bilder

Projekt Distroless bietet eine Auswahl an grundlegenden „Distroless“-Images. Sie enthalten keine Paketmanager, Shells und andere Dienstprogramme, die Sie normalerweise in der Befehlszeile sehen. Verwenden Sie daher Paketmanager wie z pip и apt wird nicht funktionieren:

FROM gcr.io/distroless/python3
RUN  pip3 install numpy

Docker-Datei mit Python 3-Distroless-Image

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

Pip ist nicht im Bild

Normalerweise wird dieses Problem durch einen mehrstufigen Build gelöst:

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/

Mehrstufige Montage

Das Ergebnis ist ein Bild mit einer Größe von 130 MB. Nicht so schlecht! Zum Vergleich: Das Standard-Python-Image wiegt 929 MB und das „dünnere“ (3,7-slim) - 179 MB, Alpenbild (3,7-alpine) ist 98,6 MB groß, während das im Beispiel verwendete Basis-Distroless-Image 50,9 MB groß ist.

Man muss darauf hinweisen, dass wir im vorherigen Beispiel ein ganzes Verzeichnis kopieren /usr/local/lib/python3.7/site-packages, die möglicherweise Abhängigkeiten enthält, die wir nicht benötigen. Obwohl klar ist, dass der Größenunterschied aller vorhandenen Python-Basisbilder unterschiedlich ist.

Zum Zeitpunkt des Verfassens dieses Artikels unterstützt Google Distroless nicht viele Bilder: Java und Python befinden sich noch im experimentellen Stadium, und Python existiert nur für 2,7 und 3,5.

Winzige Bilder

Zurück zu meiner Obsession, kleine Bilder zu erstellen.

Generell wollte ich sehen, wie distroless-Bilder aufgebaut sind. Das distroless-Projekt nutzt das Build-Tool von Google bazel. Allerdings hat die Installation von Bazel und das Schreiben eigener Bilder viel Arbeit gekostet (und um ehrlich zu sein: Das Rad neu zu erfinden macht Spaß und ist lehrreich). Ich wollte die Erstellung kleinerer Bilder vereinfachen: Die Erstellung eines Bildes sollte äußerst einfach sein. banal. Damit es für Sie keine Konfigurationsdateien gibt, genügt eine Zeile in der Konsole: просто собрать образ для <приложение>.

Wenn Sie also Ihre eigenen Images erstellen möchten, dann wissen Sie: Es gibt so ein einzigartiges Docker-Image, scratch. Scratch ist ein „leeres“ Bild, es enthält keine Dateien, obwohl es standardmäßig wiegt – wow! - 77 Byte.

FROM scratch

Kratzbild

Die Idee eines Scratch-Images besteht darin, dass Sie alle Abhängigkeiten vom Host-Computer hineinkopieren und sie entweder in einer Docker-Datei verwenden können (das ist so, als würden Sie sie kopieren). apt und von Grund auf installieren) oder später, wenn das Docker-Image materialisiert wird. Dadurch können Sie den Inhalt des Docker-Containers und damit die Größe des Bildes vollständig steuern.

Jetzt müssen wir diese Abhängigkeiten irgendwie sammeln. Vorhandene Tools wie apt ermöglichen das Herunterladen von Paketen, sind aber an den aktuellen Rechner gebunden und unterstützen schließlich weder Windows noch MacOS.

Also machte ich mich daran, mein eigenes Tool zu entwickeln, das automatisch ein Basis-Image der kleinstmöglichen Größe erstellt und auch jede beliebige Anwendung ausführt. Ich habe Ubuntu/Debian-Pakete verwendet, eine Auswahl getroffen (Pakete direkt aus den Repositorys abgerufen) und deren Abhängigkeiten rekursiv gefunden. Das Programm sollte automatisch die neueste stabile Version des Pakets herunterladen und so Sicherheitsrisiken so gering wie möglich halten.

Ich habe dem Tool einen Namen gegeben fetchy, weil er... findet und bringt... was benötigt wird [aus dem Englischen „holen“, „bringen“ – ca. Fahrbahn]. Das Tool funktioniert über eine Befehlszeilenschnittstelle, bietet aber gleichzeitig eine API.

Um ein Bild zusammenzustellen mit fetchy (Lassen Sie uns dieses Mal ein Python-Image aufnehmen), Sie müssen nur die CLI wie folgt verwenden: fetchy dockerize python. Möglicherweise werden Sie nach dem Zielbetriebssystem und dem Codenamen gefragt, weil fetchy verwendet derzeit nur Pakete, die auf Debian und Ubuntu basieren.

Jetzt können Sie auswählen, welche Abhängigkeiten (in unserem Kontext) überhaupt nicht benötigt werden, und diese ausschließen. Beispielsweise ist Python auf Perl angewiesen, obwohl es auch ohne installiertes Perl gut funktioniert.

Ergebnisse

Mit dem Befehl erstelltes Python-Image fetchy dockerize python3.5 wiegt nur 35 MB (ich bin mehr als sicher, dass es in Zukunft noch leichter gemacht werden kann). Es stellte sich heraus, dass wir es geschafft haben, weitere 15 WW vom distroless-Image einzusparen.

Sie können alle bisher gesammelten Bilder sehen hier.

Projekt - hier.

Wenn Ihnen Funktionen fehlen, erstellen Sie einfach eine Anfrage – ich helfe Ihnen gerne weiter :) Darüber hinaus arbeite ich derzeit daran, andere Paketmanager in fetchy zu integrieren, sodass keine mehrstufigen Builds erforderlich sind.

Source: habr.com

Kommentar hinzufügen