Docker Layer Squash: Wann sich --squash lohnt und wann nicht
AI generated
FROM
RUN
Docker · Images · Build
Docker Layer Squash im Detail
Kleinere Images gegen verlorenes Layer-Caching abwaegen

Der --squash Build-Flag fasst alle Layer eines Images zu einem einzigen zusammen und schafft damit kleinere, aufgeraeumte Images, kostet dabei aber das Layer-Caching zwischen Builds, das viele CI-Pipelines beschleunigt.

16 Min. Lesezeit Squash Image-Groesse Build-Caching

1. Warum Dockerfiles mit vielen Layern entstehen

Jede Anweisung in einem Dockerfile, die den Dateisystemzustand veraendert (RUN, COPY, ADD), erzeugt einen eigenen Layer, der dauerhaft im Image gespeichert bleibt. Bei gewachsenen Dockerfiles mit vielen einzelnen RUN-Befehlen fuer Paketinstallation, Konfiguration und Aufraeumarbeiten summiert sich das schnell auf 20 oder mehr Layer, von denen jeder einzelne seinen eigenen Diff im Union-Filesystem hinterlaesst.

Problematisch wird das vor allem, wenn in einem fruehen Layer eine grosse Datei angelegt und in einem spaeteren Layer wieder geloescht wird, etwa ein heruntergeladenes Archiv nach dem Entpacken. Das Loeschen entfernt die Datei zwar aus der sichtbaren Dateisystemansicht, der urspruengliche Layer mit der Datei bleibt aber im Image erhalten und traegt weiterhin zur Gesamtgroesse bei, was beim reinen Betrachten der finalen Image-Groesse leicht uebersehen wird.

2. Was --squash technisch macht

Der --squash Flag weist den Docker-Daemon an, nach einem regulaeren, layer-basierten Build alle neu erzeugten Layer des Builds zu einem einzigen Layer zusammenzufassen. Technisch werden dabei alle Dateisystem-Diffs der einzelnen Build-Schritte zu einem finalen Diff gegen das Basis-Image verrechnet, sodass am Ende exakt ein neuer Layer oberhalb des Base-Image-Layers entsteht.

Wichtig dabei: Nur die Layer, die waehrend dieses Builds neu entstanden sind, werden zusammengefasst, der Base-Image-Layer selbst bleibt als eigener Layer erhalten und wird nicht mit hineingerechnet. Dateien, die in einem fruehen Build-Schritt angelegt und in einem spaeteren wieder geloescht wurden, tauchen im finalen gesquashten Layer gar nicht mehr auf, weil nur der Endzustand des Dateisystems relevant ist.

3. Squash mit BuildKit und buildx aktivieren

Historisch war --squash ein experimentelles Feature des klassischen Docker-Builders und musste per experimental: true in der daemon.json freigeschaltet werden. Mit dem heute standardmaessig aktiven BuildKit-Builder ist die Situation etwas anders: Ueber docker buildx build steht --squash ebenfalls zur Verfuegung, teils weiterhin als experimentelle Option je nach Docker-Version, sodass ein Blick in die aktuelle Dokumentation der eigenen Docker-Version sinnvoll ist.

In der Praxis reicht meist ein einfacher Aufruf, der sich problemlos in bestehende Build-Skripte oder CI-Jobs einbauen laesst, ohne dass sich am restlichen Dockerfile etwas aendern muss. Der Build selbst dauert dabei laenger als ein normaler Build, weil zusaetzlich zum eigentlichen Bauen der Layer noch der Squash-Schritt als Nachbearbeitung erfolgt.


# Build mit Squash ueber den klassischen Builder
docker build --squash -t myapp:squashed .

# Build mit Squash ueber buildx (BuildKit)
docker buildx build --squash -t myapp:squashed --load .

# Layer-Anzahl vor und nach dem Squash vergleichen
docker history myapp:latest | wc -l
docker history myapp:squashed | wc -l

4. Vorteil: Kleinere Images durch entfernte Zwischenstaende

Der offensichtlichste Vorteil zeigt sich bei Dockerfiles, die grosse temporaere Dateien anlegen und wieder loeschen, ohne dass dies in einem einzigen RUN-Befehl mit anschliessendem rm im selben Layer geschieht. Ein Beispiel ist ein Build-Schritt, der Quellcode kompiliert und Build-Artefakte von mehreren hundert Megabyte hinterlaesst, die in einem spaeteren Schritt entfernt werden, weil nur die kompilierten Binaries im finalen Image gebraucht werden.

In solchen Faellen kann Squashing die Image-Groesse um mehrere hundert Megabyte bis in den Gigabyte-Bereich reduzieren, je nachdem wie gross die zwischenzeitlich angelegten und wieder geloeschten Dateien waren. Bei sauber geschriebenen Dockerfiles, die solche Zwischenstaende bereits ueber Multi-Stage-Builds vermeiden, faellt der Effekt dagegen deutlich geringer aus, weil es kaum noch etwas zum Zusammenfassen gibt.

5. Vorteil: Keine Layer-History mit sensiblen Zwischenstaenden

Ueber docker history oder durch Extrahieren einzelner Layer mit docker save laesst sich bei einem nicht gesquashten Image jeder Zwischenschritt nachvollziehen, einschliesslich Dateien, die in einem spaeteren Layer wieder entfernt wurden. Wird versehentlich in einem fruehen RUN-Befehl eine Zugangsdatei oder ein API-Key angelegt und erst in einem spaeteren Schritt geloescht, bleibt dieser Wert im urspruenglichen Layer fuer jeden mit Zugriff auf das Image extrahierbar.

Ein gesquashtes Image reduziert dieses Risiko, weil nur der finale Dateisystemzustand als einzelner Layer erhalten bleibt und Zwischenschritte nicht mehr rekonstruierbar sind. Das ist aber kein Ersatz fuer korrekte Secret-Handhabung ueber BuildKit-Secrets oder Multi-Stage-Builds, sondern bestenfalls eine zusaetzliche Absicherung gegen versehentliche Fehler in der Build-Logik, keine grundsaetzliche Loesung fuer den Umgang mit Geheimnissen im Build.

6. Nachteil: Kein Layer-Caching mehr zwischen Builds

Der zentrale Nachteil von --squash ist der Verlust des inkrementellen Layer-Caches zwischen aufeinanderfolgenden Builds. Normalerweise erkennt Docker anhand unveraenderter Dockerfile-Anweisungen und Build-Kontexte, welche Layer aus dem lokalen Cache oder aus der Registry wiederverwendet werden koennen, was Builds mit nur kleinen Codeaenderungen von Minuten auf Sekunden verkuerzt.

Da ein gesquashtes Image aus Docker-Sicht nur noch einen einzigen Layer oberhalb des Base-Image besitzt, gibt es fuer nachfolgende Builds nichts mehr, worauf granular aufgesetzt werden koennte. Jede noch so kleine Codeaenderung fuehrt effektiv dazu, dass der komplette Build-Prozess von vorne durchlaeuft, was insbesondere in CI-Pipelines mit haeufigen Commits die Build-Zeiten spuerbar verlaengert.

7. Multi-Stage-Builds als bessere Alternative in vielen Faellen

Fuer die meisten Anwendungsfaelle, in denen Squashing wegen grosser Zwischenartefakte in Erwaegung gezogen wird, ist ein Multi-Stage-Build die sauberere Loesung. Build-Abhaengigkeiten, Compiler und temporaere Artefakte landen in einer separaten Build-Stage, aus der am Ende nur die tatsaechlich benoetigten Dateien in eine schlanke Runtime-Stage kopiert werden, ohne dass Zwischenschritte jemals im finalen Image landen.

Der entscheidende Unterschied zu --squash ist, dass Multi-Stage-Builds das Layer-Caching innerhalb jeder einzelnen Stage vollstaendig erhalten. Aendert sich nur der Anwendungscode, nicht aber die Build-Abhaengigkeiten, greift der Cache fuer die Installationsschritte weiterhin, waehrend gleichzeitig ein ebenso schlankes finales Image entsteht wie mit Squashing, nur eben ohne dessen Cache-Nachteil.


# Dockerfile mit Multi-Stage-Build statt Squash
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
CMD ["node", "dist/server.js"]

8. Wann Squashing tatsaechlich die richtige Wahl ist

Squashing bleibt sinnvoll bei finalen Release-Images, die nur noch einmal gebaut und danach unveraendert in vielen Umgebungen verteilt werden, etwa fertige Basis-Images fuer interne Teams oder Distributions-Images, bei denen die Registry-Groesse und Pull-Zeit wichtiger sind als schnelle Wiederholungs-Builds. Auch bei Images, die aus Legacy-Dockerfiles entstehen, die nicht ohne weiteres auf Multi-Stage umgeschrieben werden koennen, ist Squashing eine pragmatische Zwischenloesung.

Nicht sinnvoll ist Squashing dagegen in aktiven Entwicklungs- oder CI-Pipelines mit haeufigen Rebuilds, wo der Verlust des Layer-Caches die Build-Zeiten spuerbar erhoeht und den eigentlichen Zweck schneller Feedback-Zyklen untergraebt. Hier ueberwiegt der Nachteil des fehlenden Caches fast immer den Vorteil der kleineren Image-Groesse.

9. Entscheidungsleitfaden fuer die Praxis

Die Faustregel lautet: Erst pruefen, ob ein Multi-Stage-Build das eigentliche Problem loest, das Zwischenstaende im finalen Image landen. In den allermeisten Faellen ist das moeglich und die deutlich bessere Wahl, weil Caching und kleine Images kein Widerspruch sind. Squashing bleibt danach als gezieltes Werkzeug fuer die verbleibenden Randfaelle wie einmalige Release-Builds oder Legacy-Dockerfiles, die sich kurzfristig nicht umstrukturieren lassen.

Wer beide Ansaetze kombinieren will, kann auch einen Multi-Stage-Build zusaetzlich mit --squash fahren, verliert dann aber trotzdem das Caching fuer den finalen Build-Lauf. In der Praxis lohnt sich diese Kombination selten, weil ein sauberer Multi-Stage-Build meist bereits die gewuenschte Image-Groesse ohne Squashing erreicht.

Ansatz Layer-Caching Image-Groesse Typischer Einsatz
Normaler Build Vollstaendig erhalten Groesser bei vielen Zwischenstaenden Aktive Entwicklung, haeufige Rebuilds
--squash Verloren fuer nachfolgende Builds Deutlich kleiner bei grossen Zwischenstaenden Finale Release-Images, Legacy-Dockerfiles
Multi-Stage-Build Vollstaendig erhalten pro Stage Klein durch selektives Kopieren Empfohlener Standardansatz
Multi-Stage + --squash Verloren fuer finalen Lauf Minimal Seltene Spezialfaelle

Mironsoft

Container-Infrastruktur, CI-Pipelines und Deployment-Automatisierung

Docker-Setups, die im Team und in Produktion tragfähig bleiben?

Wir prüfen bestehende Dockerfiles und Compose-Stacks auf Sicherheitslücken, aufgeblähte Images und fragile Build-Pipelines und bauen daraus eine Container-Infrastruktur, die schnell baut, sicher läuft und im Team nachvollziehbar bleibt.

Dockerfile-Review

Multi-Stage-Builds, Layer-Caching und Image-Größe systematisch optimieren.

Security-Audit

Container-Isolation, Secrets-Handling und Image-Scanning gegen echte Angriffsflächen absichern.

CI/CD-Integration

Build-Pipelines, Registries und Deployment-Strategien für reproduzierbare Releases aufbauen.

10. Zusammenfassung

Layer Squash: Das Wichtigste auf einen Blick

Funktionsweise

--squash fasst alle neu erzeugten Build-Layer zu einem einzigen Layer zusammen.

Vorteil

Kleinere Images, keine rekonstruierbare Historie geloeschter Zwischenstaende.

Nachteil

Layer-Caching zwischen Builds geht fuer den Squash-Layer verloren.

Empfehlung

Multi-Stage-Builds meist vorziehen, Squash gezielt fuer Release-Images.

11. FAQ: Layer Squash: Das Wichtigste auf einen Blick

1Was macht der --squash Flag bei docker build?
Der Flag fasst alle waehrend des Builds neu erzeugten Layer zu einem einzigen Layer oberhalb des Base-Image zusammen, sodass am Ende nur der finale Dateisystemzustand als ein Diff gespeichert wird.
2Reduziert Squashing immer die Image-Groesse?
Nicht zwangslaeufig. Der Effekt ist gross, wenn zwischenzeitlich grosse Dateien angelegt und wieder geloescht wurden. Bei bereits sauber geschriebenen Dockerfiles ohne solche Zwischenstaende faellt die Reduktion gering aus.
3Warum geht das Layer-Caching bei Squash verloren?
Weil das gesquashte Image aus Docker-Sicht nur noch einen einzigen Layer oberhalb des Base-Image besitzt, kann kein nachfolgender Build mehr granular auf einzelnen Zwischenschritten aus dem Cache aufsetzen.
4Ist Squash ein Ersatz fuer sichere Secret-Handhabung?
Nein. Squash verhindert nur, dass geloeschte Zwischenstaende ueber docker history extrahierbar bleiben, ersetzt aber nicht BuildKit-Secrets oder Multi-Stage-Builds als korrekten Weg, Geheimnisse aus dem Build herauszuhalten.
5Ist Multi-Stage-Build immer die bessere Wahl als Squash?
In den meisten Faellen ja, weil Multi-Stage-Builds kleine Images erzeugen und gleichzeitig das Layer-Caching pro Stage erhalten. Squash bleibt vor allem fuer Legacy-Dockerfiles oder einmalige Release-Builds relevant.
6Muss --squash in der daemon.json aktiviert werden?
Beim klassischen Builder war das teils noetig, ueber experimental: true. Mit BuildKit und docker buildx build --squash haengt die genaue Verfuegbarkeit von der Docker-Version ab, ein Blick in die aktuelle Dokumentation ist ratsam.
7Verlaengert Squash die Build-Zeit?
Ja, weil nach dem eigentlichen Bauen der Layer zusaetzlich der Squash-Schritt als Nachbearbeitung laeuft, der alle Layer-Diffs zu einem finalen Diff zusammenrechnet.
8Bleibt der Base-Image-Layer beim Squash erhalten?
Ja, nur die waehrend des aktuellen Builds neu erzeugten Layer werden zusammengefasst, der Layer des Base-Image selbst bleibt als eigener, separater Layer bestehen.
9Fuer welche Images lohnt sich Squash am ehesten?
Fuer finale Release-Images, die nur einmal gebaut und danach unveraendert verteilt werden, sowie fuer Legacy-Dockerfiles mit grossen Zwischenstaenden, die sich kurzfristig nicht auf Multi-Stage umstellen lassen.
10Kann ich Multi-Stage-Build und Squash kombinieren?
Technisch ja, dabei geht aber trotzdem das Caching fuer den finalen Build-Lauf verloren. In der Praxis lohnt sich das selten, weil ein sauberer Multi-Stage-Build meist schon die gewuenschte Groesse ohne Squash erreicht.