depends_on und Healthchecks in Compose - Container in der richtigen Reihenfolge starten

depends_on und Healthchecks in Compose - Container in der richtigen Reihenfolge starten

depends_on allein reicht nicht — wer wirklich auf einen fertigen Dienst warten will, braucht Healthchecks.

Das Problem mit bloßem depends_on

Ein klassischer Fehler: Die App startet, die Datenbank ist noch nicht bereit, die Verbindung schlägt fehl.

services:
  app:
    image: myapp
    depends_on:
      - db   # Wartet nur bis der Container läuft, NICHT bis Postgres bereit ist

  db:
    image: postgres:16

Docker Compose wartet hier nur darauf, dass der db-Container gestartet wurde — nicht darauf, dass Postgres tatsächlich Verbindungen annimmt. Das sind zwei sehr unterschiedliche Dinge.

Healthcheck definieren

Der Schlüssel liegt im healthcheck-Block des abhängigen Dienstes:

services:
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: secret
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 3s
      retries: 5
      start_period: 10s
  • test: Der Befehl, der geprüft wird (Exit-Code 0 = healthy)
  • interval: Wie oft geprüft wird
  • timeout: Maximale Wartezeit pro Check
  • retries: Wie viele fehlgeschlagene Checks bis unhealthy
  • start_period: Startzeit, in der Fehlschläge nicht zählen

depends_on mit Condition verknüpfen

Jetzt kann die App tatsächlich warten, bis die Datenbank bereit ist:

services:
  app:
    image: myapp
    depends_on:
      db:
        condition: service_healthy

  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: secret
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 3s
      retries: 5
      start_period: 10s

Die drei Condition-Optionen

| Condition | Bedeutung |
|---|---|
| service_started | Default — Container ist gestartet (entspricht altem Verhalten) |
| service_healthy | Healthcheck meldet healthy |
| service_completed_successfully | Container hat mit Exit-Code 0 beendet (für Init-Jobs) |

service_completed_successfully ist nützlich für Migrationen:

services:
  migrate:
    image: myapp
    command: ["python", "manage.py", "migrate"]
    depends_on:
      db:
        condition: service_healthy

  app:
    image: myapp
    depends_on:
      migrate:
        condition: service_completed_successfully
      db:
        condition: service_healthy

Praxisbeispiele für Healthchecks

Redis:

healthcheck:
  test: ["CMD", "redis-cli", "ping"]
  interval: 5s
  retries: 3

MySQL:

healthcheck:
  test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
  interval: 10s
  timeout: 5s
  retries: 5

HTTP-Service:

healthcheck:
  test: ["CMD-SHELL", "curl -f http://localhost:8080/health || exit 1"]
  interval: 10s
  timeout: 5s
  retries: 3
  start_period: 30s

Health-Status prüfen

docker ps          # Spalte STATUS zeigt (healthy) oder (unhealthy)
docker inspect --format='{{.State.Health.Status}}' <container>

Wer seine Compose-Stacks zuverlässig starten will, kommt an der Kombination aus healthcheck und condition: service_healthy nicht vorbei. Das kleine Extra an Konfiguration verhindert eine ganze Klasse von Race-Condition-Fehlern.