Ein Image-Layer ist eine einzelne Schicht im Dateisystem eines Container-Images. Jede Anweisung im Dockerfile, die Dateien verändert, erzeugt eine solche Schicht. Ein Image ist damit kein Paket, sondern ein Stapel von Änderungen, aus dem beim Start ein vollständiges Dateisystem zusammengesetzt wird.

Warum geschichtet statt kopiert

Der Vorteil ist Deduplizierung und Cache-Wiederverwendung. Zwei Wege sind entscheidend:

  • Teilen zwischen Images: Liegt die Basis debian:13-slim bereits lokal, wird sie für ein weiteres Image nicht erneut geladen. Auch auf der Platte existiert der Inhalt nur einmal.
  • Wiederverwendung im Build-Cache: Bleiben die Anweisungen bis zu einer Zeile unverändert, nimmt der Builder die bereits gebauten Schichten wieder. Deshalb bringt man die selten geänderten Schritte nach oben: erst Abhängigkeiten, dann Quellcode.

Nur der letzte Zustand zählt

Ein wichtiges Detail: Wird eine Datei in einer späteren Schicht gelöscht, verschwindet sie aus dem Ergebnis – aber nicht aus dem Image. Die Schicht, die sie enthielt, bleibt bestehen und wird weiterhin übertragen. Ein rm am Ende eines RUN spart deshalb nur dann Platz, wenn es im selben Befehl wie das Anlegen erfolgt:

# Schlecht: Die Paketlisten bleiben in einer früheren Schicht im Image
RUN apt-get update
RUN apt-get install -y curl
RUN rm -rf /var/lib/apt/lists/*

# Gut: Anlegen und Aufräumen in einer Schicht
RUN apt-get update && apt-get install -y --no-install-recommends curl \
    && rm -rf /var/lib/apt/lists/*

Dasselbe gilt für Geheimnisse: Ein Token, das in einer RUN- oder ARG-Zeile auftaucht, bleibt über die Schichthistorie auslesbar, auch wenn es später gelöscht wird. Dafür gibt es BuildKit-Secrets, die nur während des Builds eingebunden werden.

Schreibschicht zur Laufzeit

Beim Start legt die Laufzeitumgebung eine beschreibbare Schicht über den Stapel (Copy-on-Write). Geänderte Dateien werden dabei aus der darunterliegenden Schicht in die obere kopiert. Daraus folgen zwei Regeln im Betrieb:

  1. Viele Schreibzugriffe (Datenbanken, Logs) sind im Overlay langsam. Daten gehören in ein Volume.
  2. Die Schreibschicht gehört dem Container. Wird er gelöscht, ist sie weg.

Werkzeuge

# Größe je Anweisung anzeigen
docker history mein-image:1.0

# Gesamtzahl und Größe der Schichten
docker image inspect mein-image:1.0 --format '{{len .RootFS.Layers}}'

# Ungenutzte Schichten freigeben
docker image prune

Wer die Schichten einmal grafisch durchgeht (etwa mit dive), findet sehr schnell verschenkten Platz: Paketcaches, Testdateien und doppelt kopierte Verzeichnisse. Ein gut gebautes Image hat wenige, große Schichten in den unteren Ebenen und eine kleine Änderungsschicht oben – so bleibt der Build schnell und das Image schlank.

Verwandte Grundlagen: Docker-Image, Dockerfile, Registry, Buildah.