🐳 Der Beginn der Docker-Image-Diät: Den Stammbaum mit docker history entschlüsseln

Manchmal stellt man fest, dass die Image-Größe weit über 1 GB liegt, obwohl man doch nur eine kleine Anwendung gestartet hat. Man fragt sich verwirrt: „Was habe ich da bloß hineingepackt?“ In solchen Momenten ist es unerlässlich, den „Stammbaum“ des Images genau unter die Lupe zu nehmen.

Docker-Layer-Diät

„Was hast du denn bloß gefressen, dass du so riesig geworden bist?“

Ein Docker-Image gleicht einer Zwiebel mit vielen Schichten (Layern). docker history ist ein Befehl, der wie ein Röntgenbild diese Schichten nacheinander freilegt, um den Übeltäter zu identifizieren.

Die grundlegende Anwendung ist denkbar einfach:

# Grundlegende Verwendung
docker history [Optionen] <Image-Name:Tag>

# Beispiel: Historie meiner App überprüfen
docker history my-app:latest

Führen Sie den Befehl aus, und die Historie des Images wird in umgekehrter Reihenfolge angezeigt, beginnend mit dem neuesten Layer bis zum Basis-Image.

IMAGE          CREATED          CREATED BY                                      SIZE
a6215f271958   5 minutes ago    /bin/sh -c #(nop)  CMD ["/bin/sh"]               0B
<missing>      7 weeks ago      /bin/sh -c #(nop) ADD file:f28242cf608f6...     7.81MB

Achten Sie hier genau auf den SIZE-Eintrag. Wenn dort Hunderte von MB stehen, wo eigentlich 0B sein sollten? Dann ist dieser Layer ein Kandidat für die Diät. Mit etwas Erfahrung spürt man schnell, wo „etwas faul ist“.

**💡 Nützlicher Tipp: --no-trunc**

Die Standardausgabe kürzt lange Befehle in der Mitte ab. Mit der Option --no-trunc können Sie den vollständigen Befehl ohne Kürzung sehen, was für eine genaue Analyse unerlässlich ist.

docker history --no-trunc my-app:latest


Praxisbeispiel: „Der Übeltäter war chown

Ich erzähle Ihnen eine wahre Geschichte, die ich selbst erlebt habe: Ich hatte Projektdateien von 150 MB Größe gebaut, doch das Image war seltsamerweise über 300 MB groß. Der Übeltäter waren zwei scheinbar harmlose Zeilen in meinem Dockerfile.

[Ineffiziente Methode: Zwei Layer erstellen]

# 1. Dateien kopieren (standardmäßig als root kopiert)
COPY . .

# 2. Eigentümer aus Sicherheitsgründen ändern (als separater Befehl ausgeführt)
RUN chown -R appuser:appgroup /app

Nach dem Build und einer Überprüfung mit docker history ergab sich folgendes Bild:

IMAGE          CREATED BY                                        SIZE
<layer_id_2>   /bin/sh -c chown -R appuser:appgroup /app         150MB  <-- (Hier liegt das Problem!)
<layer_id_1>   /bin/sh -c #(nop) COPY dir:abc in /app            150MB

Hier zeigt sich die Tücke der Docker-Layer. Wenn in Schritt 1 die 150 MB Dateien kopiert werden, entsteht ein Layer. Wenn aber in Schritt 2 chown ausgeführt wird, denkt Docker: „Oh, die Dateinformationen (Besitzrechte) haben sich geändert? Dann muss ich einen weiteren Layer im geänderten Zustand erstellen!“ und kopiert die bestehenden 150 MB erneut, um einen neuen Layer aufzubauen.

Das Ergebnis: Der Inhalt ist zwar identisch, aber die Dateien mit unterschiedlichen Besitzrechten werden doppelt gespeichert, wodurch sich die Größe verdoppelt.


Die Lösung: Eine Ein-Zeilen-Diät!

Die Lösung ist einfach: Man fasst die Layer zusammen, indem man die Besitzrechte direkt beim Kopieren festlegt.

[Effiziente Methode: Ein Layer erstellen]

# Besitzrechte gleichzeitig mit dem Kopieren festlegen!
COPY --chown=appuser:appgroup . .

Nachdem das Dockerfile so angepasst wurde, zeigt docker history ein dramatisches Ergebnis:

IMAGE          CREATED BY                                               SIZE
<layer_id_1>   /bin/sh -c #(nop) COPY --chown=appuser... dir:abc       150MB

Sehen Sie? Nur ein einziger Layer wurde erstellt, und die Image-Größe ist wieder schlank auf 150 MB geschrumpft. Zwei Befehlszeilen zu einer zusammenzufassen, hat die Größe halbiert.


Fazit: Nach dem Build immer die Historie prüfen!

Vergessen Sie nicht: Ein Docker-Image bedeutet ein Layer pro Befehlszeile.

Führen Sie nach dem Build, so wie Sie auch nach dem Schreiben von Code Tests durchführen, routinemäßig docker history --no-trunc aus. Wenn Sie sich fragen: „Warum ist dieses apt-get so schwer?“, oder „Warum wurde dieser Layer überhaupt getrennt?“, werden Sie feststellen, dass Sie nach und nach ein sehr leichtes und effizientes System aufbauen.

Denn unnötige Layer sind der Feind Ihres Systems!


Hat Ihnen das geholfen? Wenn ja, freuen wir uns über ein Like!

Lesen Sie auch verwandte Artikel.

Verwandte Artikel

Alles über Docker Shared Memory (shm_size und ipc)

Docker: Container-Kommunikation über Host-Ports ohne Netzwerk-Sharing

Warum sollten wir Docker-Volumes kopieren?