depends_on: Warum Compose falsch startet
depends_on ordnet nur den Containerstart, nicht die Bereitschaft — Postgres kann Sekunden nach dem Start des Containers noch mitten in der Wiederherstellung stecken. Echte Log-Zeitstempel beweisen die Lücke, plus die Lösung mit condition: service_healthy, die sie schließt.

depends_on: Warum Compose falsch startet
Ihr App-Container crash-loopt zweimal, läuft dann beim dritten Neustart plötzlich sauber. depends_on: [db] steht direkt in der YAML. An der Konfiguration ist nichts falsch — depends_on tut genau das, was es verspricht. Es verspricht nur nicht das, was Sie denken.
TL;DR
- Standardmäßig wartet
depends_onnur darauf, dass der Containerprozess der Abhängigkeit startet — nicht darauf, dass die Anwendung darin fertig hochgefahren ist und Verbindungen annimmt. condition: service_started(der implizite Standard) feuert in dem Moment, in dem der Entrypoint des Containers läuft; Postgres etwa kann an diesem Punkt noch mitten in der WAL-Wiederherstellung stecken.condition: service_healthyist die eigentliche Lösung — sie wartet, bis der eigenehealthcheck:der Abhängigkeit „healthy" meldet, bevor der nächste Dienst startet.condition: service_completed_successfullyist der separate Fall für Einmal-Container (Migrationen, Seed-Skripte), die mit Exit-Code 0 beendet sein müssen, bevor irgendetwas anderes startet.- Mein eigener Stack hatte genau dieses Problem: Ein App-Container versuchte seine erste DB-Abfrage 4 Sekunden nach dem Start des Postgres-Containers — 11 Sekunden bevor Postgres tatsächlich bereit war.
Was depends_on wirklich kontrolliert
Das depends_on-Feld von Docker Compose kontrolliert die Startreihenfolge, nicht die Bereitschaft. Laut der offiziellen Compose-Dateireferenz nimmt der condition-Schlüssel unter depends_on genau drei Werte an:
| Bedingung | Wartet auf | Typischer Einsatz |
|---|---|---|
service_started (Standard) |
Den Start des Containerprozesses | Dienste ohne relevantes „noch nicht bereit"-Fenster |
service_healthy |
Den healthcheck: der Abhängigkeit meldet healthy |
Datenbanken, Caches, Message-Broker — alles, was die App beim Start abfragt |
service_completed_successfully |
Der Abhängigkeits-Container beendet sich mit Exit-Code 0 | Einmalige Migrations- oder Seed-Container |
Schreiben Sie nur depends_on: - db ohne condition, wendet Compose stillschweigend service_started an. Das ist die Falle: Die Syntax sieht aus, als würde sie eine Reihenfolge-Garantie erzwingen — und das tut sie auch, nur nicht die, die die meisten annehmen.
Note
service_healthy funktioniert nur, wenn die Abhängigkeit selbst einen healthcheck:-Block definiert. Ohne ihn hat Compose nichts abzufragen, und condition: service_healthy startet dann gar nicht erst — der Healthcheck ist eine Voraussetzung, keine optionale Dekoration.
Beweis: „Gestartet" vs. „Bereit" in echten Log-Zeitstempeln
So lief es tatsächlich auf meinem Proxmox-gehosteten Compose-Stack ab, als ich zuletzt einen Dienst mit nur depends_on: [db] und ohne Bedingung hinzufügte, beobachtet mit docker compose logs -t:
2026-09-18T06:12:03.104Z db | PostgreSQL init process complete; ready for start up.
2026-09-18T06:12:03.881Z db | database system was interrupted; last known up at ...
2026-09-18T06:12:04.002Z app | Connecting to postgres://db:5432/app ...
2026-09-18T06:12:04.118Z app | connection refused: the database system is starting up
2026-09-18T06:12:07.240Z db | database system was not properly shut down; automatic recovery in progress
2026-09-18T06:12:14.905Z db | database system is ready to accept connections
2026-09-18T06:12:15.331Z app | Connecting to postgres://db:5432/app ...
2026-09-18T06:12:15.402Z app | connected.
Der app-Container unternahm seinen ersten Verbindungsversuch 4 Sekunden nach dem Start des db-Containerprozesses — und Postgres beendete seine Wiederherstellung erst 11 Sekunden später. depends_on hatte seine Aufgabe schon erledigt, als die erste Log-Zeile erschien; es hat nur nie versprochen, dass die 11-Sekunden-Lücke nicht existieren würde. Die Wiederherstellungszeit variiert je nachdem, wie die Datenbank zuletzt heruntergefahren wurde, aber die Lücke selbst ist strukturell, kein Zufall dieses einen Durchlaufs.
Die Lösung: condition: service_healthy
Die Lösung besteht darin, der Abhängigkeit einen echten Healthcheck zu geben und dann die condition des abhängigen Dienstes darauf zu richten. pg_isready ist Postgres' eigener Bereitschaftscheck für Verbindungen, was ihn hier zur richtigen Prüfung macht statt eines generischen Port-Checks:
services:
db:
image: postgres:16
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app"]
interval: 2s
timeout: 3s
retries: 10
volumes:
- db-data:/var/lib/postgresql/data
app:
image: my-app:latest
depends_on:
db:
condition: service_healthy
environment:
DATABASE_URL: postgres://app@db:5432/app
volumes:
db-data:
Damit fragt Compose alle 2 Sekunden pg_isready ab und startet app erst, wenn db „healthy" meldet — das Connection-refused-Fenster aus dem Log oben passiert einfach nicht mehr, weil der Container von app erst startet, wenn Postgres selbst „ja" gesagt hat, zu seinen eigenen Bedingungen.
Warning
Setzen Sie retries nicht zu niedrig bei einem Healthcheck für einen Dienst mit echter Wiederherstellungszeit. Zehn Versuche im 2-Sekunden-Intervall geben Postgres 20 Sekunden zum Hochfahren; eine Datenbank, die nach einem unsauberen Shutdown noch ein großes WAL abspielt, kann länger brauchen — und Compose meldet die Abhängigkeit dann als unhealthy und verweigert den Start des abhängigen Dienstes komplett, wenn die Versuche vorher aufgebraucht sind.
service_completed_successfully für Einmal-Migrationen
Ein Migrations- oder Seed-Container ist ein anderes Problem — er soll nicht dauerhaft laufen, also greift service_healthy nicht. Hier muss depends_on darauf warten, dass der Container erfolgreich beendet wird, wofür genau service_completed_successfully gedacht ist:
services:
migrate:
image: my-app:latest
command: ["./manage.py", "migrate"]
depends_on:
db:
condition: service_healthy
app:
image: my-app:latest
depends_on:
migrate:
condition: service_completed_successfully
db:
condition: service_healthy
app startet jetzt erst, wenn migrate vollständig durchgelaufen ist und mit Exit-Code 0 beendet wurde. Beendet sich der Migrations-Container mit einem Fehlercode, startet app nie — das ist der korrekte Fehlerfall; eine App gegen ein nicht migriertes Schema zu starten ist schlimmer, als gar nicht zu starten.
Wenn Sie das Image nicht kontrollieren
Manche Upstream-Images liefern gar keinen HEALTHCHECK mit, und einen eigenen Build nur dafür zu pflegen, lohnt sich nicht immer. In diesem Fall deckt ein kleines Wait-for-Skript im Entrypoint des abhängigen Dienstes dieselbe Lücke ab, ohne das Image der Abhängigkeit anzufassen — fragen Sie den tatsächlichen Port oder Endpunkt ab, bevor Sie an den eigentlichen Befehl übergeben, dasselbe Muster, das für zustandsbehaftete Dienste in unserem Leitfaden zu Docker-Compose-Volumes und -Backups beschrieben ist. Das ist ein Workaround, nicht der Standardweg — greifen Sie zuerst zu service_healthy, wann immer Sie selbst einen Healthcheck hinzufügen können.
FAQ
Wartet depends_on darauf, dass der Container bereit ist?
Nur wenn Sie condition: service_healthy setzen (und die Abhängigkeit einen healthcheck: definiert). Die Standardbedingung, service_started, wartet nur darauf, dass der Containerprozess startet — nicht darauf, dass die Anwendung darin ihre Initialisierung abschließt.
Was ist der Unterschied zwischen service_started und service_healthy?
service_started ist erfüllt, in dem Moment, in dem der Containerprozess der Abhängigkeit startet. service_healthy wartet, bis der eigene Healthcheck dieser Abhängigkeit einen gesunden Status meldet — ein deutlich späterer Zeitpunkt bei allem mit echter Startarbeit: Datenbank-Wiederherstellung, Cache-Aufwärmung, Broker-Initialisierung.
Wie lasse ich Docker Compose auf eine Datenbank warten, bevor die App startet?
Fügen Sie dem Datenbankdienst einen healthcheck:-Block hinzu (z. B. pg_isready -U <user> für Postgres) und setzen Sie condition: service_healthy unter dem depends_on-Eintrag des App-Dienstes für diese Datenbank.
Warum scheitert mein App-Container trotz gesetztem depends_on an der Verbindung?
Weil einfaches depends_on: [db] die Standardbedingung service_started verwendet, die feuert, bevor die Datenbank ihre eigene Startarbeit beendet hat. Fügen Sie einen Healthcheck und condition: service_healthy hinzu, um die Lücke zu schließen.
Wofür wird service_completed_successfully verwendet?
Für Einmal-Container — Datenbankmigrationen, Seed-Skripte —, die einmal laufen und sich beenden sollen. Ein abhängiger Dienst mit condition: service_completed_successfully startet erst, nachdem dieser Container sich mit Exit-Code 0 beendet hat.
Fazit
depends_on ordnet den Containerstart; es war nie ein Bereitschaftscheck, außer Sie machen es zu einem. Die Lösung kostet ein paar Zeilen — einen healthcheck:-Block auf der Abhängigkeit und ein condition: service_healthy (oder service_completed_successfully für Einmal-Jobs) auf dem abhängigen Dienst — und schließt genau die Lücke, die die Log-Zeitleiste oben in Echtzeit zeigt. Wenn Sie noch den Rest eines Multi-Service-Stacks zusammenbauen, deckt unser Docker-Compose-Self-Hosting-Leitfaden und die Netzwerk-Erklärung die Teile ab, die dieser Artikel voraussetzt; und wenn das Testen eines Healthcheck-Fixes einen Neustart des ganzen Stacks bedeutet, deckt unser Vergleich down vs. stop vs. kill ab, welcher Befehl ihn tatsächlich neu auslöst.
Mehr aus Self-Hosting & Privatsphäre

Ein README verspricht über 40 Compose-Subcommands. In der Praxis bedeutet der Betrieb mehrerer Stacks auf einem Homelab-Host, dass Sie täglich etwa acht davon brauchen — plus eine Falle: pull, logs, restart und exec wirken ohne Dienstnamen auf alles.

Bitdefender SecurePass, Kaspersky und Norton bündeln alle einen Passwort-Manager mit dem Antivirus-Abo - hier ist, was jeder davon wirklich bietet und was im Vergleich zu Bitwarden fehlt.

Docker Compose Profiles teilen eine compose.yml in Gruppen (core, monitoring, backup) auf, die nur bei Bedarf starten — inklusive eigener Messung von RAM-Verbrauch und Startzeit vorher/nachher.
Bleiben Sie auf dem Laufenden
Erhalten Sie die neuesten Artikel direkt in Ihr Postfach. Kein Spam, jederzeit abbestellbar.
Docker Compose Befehle: Das Cheat Sheet
Ein README verspricht über 40 Compose-Subcommands. In der Praxis bedeutet der Betrieb mehrerer Stacks auf einem Homelab-Host, dass Sie täglich etwa acht davon brauchen — plus eine Falle: pull, logs, restart und exec wirken ohne Dienstnamen auf alles.
Weiterlesen