Zum Hauptinhalt springen
Self-Hosting & Privatsphäre

Docker Compose: Build, Pull oder --no-cache

Was docker compose up, --build und build --no-cache jeweils wirklich neu bauen, die Volume-Falle, die einen frisch gebauten Container trotzdem veraltet aussehen laesst, und echte Rebuild-Zeiten aus diesem Homelab.

milanbuha0023. August 20266 Min. LesezeitRead in English
TeilenXin
Docker Compose: Build, Pull oder --no-cache

Ich habe ein Dockerfile bearbeitet, docker compose up -d ausgeführt, und der Container kam mit genau demselben Code zurück wie vorher. Keine Fehlermeldung, keine Warnung — nur Stille, und ein Dienst, der gestartet aussah, aber nicht der war, den ich gerade geändert hatte.

TL;DR

  • Ein einfaches docker compose up prüft nie, ob sich ein Dockerfile geändert hat — es verwendet das bereits lokal getaggte Image, falls eines existiert.
  • docker compose up --build baut neu, nutzt dabei aber weiterhin Dockers Layer-Cache — nur die Layer ab dem ersten geänderten COPY laufen tatsächlich erneut.
  • docker compose build --no-cache verwirft jeden gecachten Layer und baut komplett neu — am langsamsten, aber der einzige, der garantiert jede Änderung übernimmt.
  • Die Dateien eines wirklich neu gebauten Images können trotzdem veraltet aussehen, wenn ein Volume über das App-Verzeichnis gemountet ist — das ist ein Volume-Problem, kein Build-Cache-Problem.
  • Ziehen Sie ein fertiges Image, wenn es ein offizielles Image ohne lokalen Code ist; bauen Sie nur, wenn tatsächlich ein Dockerfile oder lokaler Quellcode laufen muss.

KEY-STAT: 3 — Unterschiedliche Dinge, die "meinen Container neu bauen" in Compose bedeuten kann — und jedes baut eine andere Menge neu

Was docker compose up mit Ihrem Image wirklich macht

docker compose up schaut sich den Image-Tag an, auf den ein Dienst verweist, und verwendet ihn — Punkt —, falls dieser Tag bereits lokal existiert. Es vergleicht das Dockerfile nicht, prüft keine Datei-Zeitstempel im Build-Kontext und weiß oder interessiert sich nicht dafür, dass Sie gerade vor fünf Sekunden eine per COPY eingebundene Datei geändert haben. Das ist kein Bug; ein einfaches up soll genau das starten, was bereits gebaut ist — genauso wie up bei einem reinen Pull-Dienst nur das zuletzt gezogene Image startet. Die Verwirrung entsteht, weil man erwartet, dass "starten" auch "bei Bedarf neu bauen" bedeutet — Compose hält diese beiden Dinge bewusst getrennt.

Die drei Befehle und was jeder davon neu baut

BefehlWas er tut
docker compose upStartet vorhandene Container/Images unverändert; baut nie neu, prüft nie, ob sich das Dockerfile geändert hat
docker compose up --buildBaut zuerst neu, startet dann — nutzt aber weiterhin den Layer-Cache, sodass nur Layer nach der ersten geänderten Anweisung tatsächlich erneut laufen
docker compose build --no-cacheVerwirft jeden gecachten Layer und führt das gesamte Dockerfile jedes Mal komplett neu aus

Warum --build allein manchmal trotzdem veraltet aussieht

Dockers Layer-Cache arbeitet von oben nach unten: Jede Dockerfile-Anweisung erzeugt einen Layer, und ein Layer wird wiederverwendet, solange seine Eingaben (die Anweisung selbst, und bei COPY/ADD der Dateiinhalt) unverändert sind. --build respektiert diesen Cache — es deaktiviert ihn nicht. Ist also ein COPY package.json .-Layer weit oben im Dockerfile unverändert, aber ein späterer COPY . .-Layer mit Ihrem eigentlichen Code hat sich geändert, läuft nur dieser Layer und alles danach erneut. Genau das will man in der Regel — schnelle, korrekte Rebuilds. Es überrascht nur diejenigen, die erwarten, dass --build dasselbe wie --no-cache bedeutet; das tut es nicht.

Hinweis

--pull ist ein eigenes Flag, unabhängig von beiden — es prüft die Registry auf eine neuere Version des im FROM referenzierten Basis-Images, bevor gebaut wird, unabhängig davon, ob der Cache für Ihre eigenen Layer genutzt wird. Kombinieren Sie --no-cache --pull für den tatsächlich saubersten Rebuild: neues Basis-Image, null wiederverwendete Layer.

Die Volume-Falle

Ein tatsächlich neu gebautes Image kann trotzdem veraltet aussehen, aus einem Grund, der nichts mit dem Build-Cache zu tun hat: ein benanntes oder anonymes Volume, das über denselben Pfad wie Ihr Anwendungscode gemountet ist. Mountet ein Compose-File ein Volume auf /app, und dieses Volume enthält bereits alte Dateien aus einem vorherigen Lauf, startet der Container zwar mit dem neuen Image, aber der Inhalt des Volumes überdeckt, was das Image gerade gebaut hat — die alten Dateien gewinnen, weil Volumes an diesem Pfad über das Image-Dateisystem gemountet werden.

Warnung

Sieht ein Rebuild im Build-Log korrekt aus, verhält sich der laufende Container aber weiterhin wie der alte Code, prüfen Sie zuerst auf ein über den Code-Pfad gemountetes Volume, bevor Sie annehmen, der Build-Cache würde Sie belügen. docker compose down -v (entfernt Volumes, siehe der Guide zu Volumes und Backups) behebt das — oder docker compose up --build --renew-anon-volumes, wenn speziell ein anonymes Volume der Übeltäter ist.

Was ein erzwungener Rebuild wirklich kostet

Auf dem Server dieses Homelabs dauert ein docker compose build --no-cache für einen kleinen Dienst mit eigenem Dockerfile — ein Python-basierter Hintergrund-Worker mit ein paar pip-Abhängigkeiten — ungefähr zwei Minuten: jedes OS-Paket und jede pip-Abhängigkeit wird komplett neu installiert, nichts wird wiederverwendet. Derselbe Rebuild mit intaktem Cache und ohne tatsächliche Änderung ist in einstelligen Sekunden fertig, weil jeder Layer aus dem Cache kommt und Docker das bestehende Image nur neu taggt. Genau diese Lücke ist der Grund, warum --no-cache nicht der Standard ist — bei den meisten Änderungen müssen wirklich nur der letzte Layer oder zwei neu gebaut werden, und ein erzwungener kompletter Rebuild wirft das ohne jeden Nutzen weg.

Pull oder Build: wann ein fertiges Image die richtige Wahl ist

Ziehen Sie ein fertiges Image — im Stil von image: postgres:16, ohne build:-Schlüssel —, wann immer der Dienst eine fertige Anwendung ohne lokale Code-Änderungen ist: eine Datenbank-Engine, Jellyfin, Vaultwarden, Caddy. Es gibt nichts zu bauen, und Pullen liefert ein von den Maintainern getestetes Image, ganz ohne die obigen Build-Cache-Fragen. Greifen Sie nur dann zu build: aus einem lokalen Dockerfile, wenn der Dienst tatsächlich Ihren eigenen Code ausführt oder ein Basis-Image braucht, das über das hinausgeht, was Umgebungsvariablen und Volumes konfigurieren können — sonst fügt build: nur Rebuild-Cache-Komplexität für ein Problem hinzu, das noch gar nicht existiert.

Entscheidungshilfe

SymptomWas ausführen
Stack zum ersten Mal gestartet, Images existieren bereits lokaldocker compose up -d
Ein Dockerfile oder in das Image kopierter Code wurde geändertdocker compose up --build -d
--build lief, der Container sieht aber weiterhin wie der alte Code aus, und kein Volume liegt über dem Code-Pfaddocker compose build --no-cache, dann up -d
Container sieht selbst nach einem sauberen --no-cache-Rebuild veraltet ausAuf ein über das App-Verzeichnis gemountetes Volume prüfen — vermutlich down -v oder --renew-anon-volumes
Auch das neueste Basis-Image gewünscht, nicht nur die eigenen Layerdocker compose build --no-cache --pull
Fertiger Dienst, gar kein lokales DockerfileKein build:-Schlüssel — nur image: und docker compose pull zum Aktualisieren

Das Neustart-Verhalten nach einem Rebuild ist eine eigene, unabhängige Entscheidung — siehe der Guide zu den Restart-Policies —, und auch welches Netzwerk ein neu gebauter Container betritt, ändert sich dadurch nicht, behandelt im Docker-Compose-Networking-Guide. Build, Restart-Policy und Netzwerk sind drei unabhängige Entscheidungen pro Dienst.

Fazit

docker compose up baut nie von selbst neu, --build baut neu, vertraut dabei aber weiterhin dem Layer-Cache, und --no-cache ist der einzige Befehl, der ein Ergebnis von Grund auf garantiert — mit echtem Zeitkosten, nicht nur als Flag aus Gewohnheit. Sieht ein Rebuild auch nach --no-cache noch veraltet aus, hören Sie auf, den Build zu verdächtigen, und prüfen Sie stattdessen, ob ein Volume über den Code-Pfad gemountet ist.

Häufige Fragen

Baut docker compose up das Image automatisch neu?

Nein. docker compose up startet das bereits lokal getaggte Image und prüft nie, ob sich das Dockerfile oder der Build-Kontext geändert haben. Verwenden Sie docker compose up --build, um vor dem Start einen Rebuild zu erzwingen.

Was ist der Unterschied zwischen docker compose up --build und docker compose build --no-cache?

--build baut neu, nutzt aber weiterhin Dockers Layer-Cache, sodass nur Layer nach der ersten geänderten Anweisung tatsächlich erneut laufen. --no-cache verwirft den gesamten Cache und baut jeden Layer von Grund auf neu, was langsamer ist, aber garantiert, dass jede Anweisung erneut ausgeführt wird.

Warum zeigt mein Docker-Container meine Code-Änderungen nicht an?

Meistens wurde entweder das Image nie neu gebaut (ein einfaches docker compose up baut nicht neu), oder ein Volume ist über denselben Pfad wie der Anwendungscode gemountet, sodass die alten Inhalte des Volumes die Dateien des gerade gebauten Images an diesem Pfad überdecken.

Sollte ich bei jedem Rebuild --no-cache verwenden?

Nein — bei den meisten Änderungen hat sich tatsächlich nur der letzte Layer oder zwei geändert, und --build allein erkennt das bereits korrekt und deutlich schneller. Greifen Sie zu --no-cache, wenn Sie konkret vermuten, dass der Cache selbst veraltet oder falsch ist, nicht als Routine.

Ähnliche Artikel

Mehr aus Self-Hosting & Privatsphäre

Bleiben Sie auf dem Laufenden

Erhalten Sie die neuesten Artikel direkt in Ihr Postfach. Kein Spam, jederzeit abbestellbar.

Als Nächstes lesen

Docker Compose: Down, Stop oder Kill

Ich habe docker compose stop ausgefuehrt und erwartet, dass der ganze Stack verschwindet. Container, Netzwerk und Volumes blieben trotzdem bestehen -- was stop, down, down -v und kill wirklich abbauen, und wann welcher Befehl der richtige ist.

Weiterlesen