Zum Inhalt

Docker Compose mit Healthchecks und sicheren Neustarts zuverlässiger machen

Veröffentlicht am 4. September 2026 · Geschätzte Lesezeit: 10 Minuten

Ein laufender Container ist nicht automatisch ein einsatzbereiter Dienst. Mit einem lokalen Healthcheck erkennt Docker, ob die Anwendung im Container wirklich antwortet; depends_on kann abhängige Dienste beim Start darauf warten lassen und eine Restart-Policy startet beendete Container kontrolliert neu.[1][5] Plane etwa 30 bis 45 Minuten für Einrichtung und Fehlerprobe ein.

Voraussetzungen

  • Ein Linux-Server mit Docker Engine und dem Docker-Compose-Plugin
  • Ein vorhandenes Compose-Projekt mit einer compose.yaml
  • Terminalzugriff auf den Projektordner
  • Ein aktuelles Backup der Compose-Datei, Datenbanken und eingebundenen Volumes

1. Projektzustand und Werkzeuge prüfen

Wechsle in den Ordner deines Compose-Projekts. Ersetze <projektordner> durch den vollständigen Pfad zu diesem Ordner:

cd <projektordner>

Zeige die installierten Versionen an:

docker version
docker compose version

Prüfe danach die vorhandene Konfiguration:

docker compose config

Der letzte Befehl muss ohne Fehler enden. Zeige außerdem alle zum Projekt gehörenden Container an:

docker compose ps --all

docker compose ps listet Zustand und veröffentlichte Ports; mit --all erscheinen auch beendete Container.[10] Notiere die Namen der Dienste, die voneinander abhängen.

2. Konfiguration und Daten sichern

Erstelle vor jeder Änderung eine datierte Kopie der Compose-Datei:

cp compose.yaml "compose.yaml.vor-healthcheck-$(date +%F-%H%M)"

Verwendet dein Projekt docker-compose.yml, ersetze compose.yaml in allen Sicherungs- und Rückweg-Befehlen durch diesen Dateinamen. Die Kopie sichert nur die Konfiguration. Sichere Datenbanken und Anwendungsdaten zusätzlich mit dem dokumentierten Backup-Verfahren der jeweiligen Anwendung.

Liste die eingebundenen Volumes auf, damit du keine Datenspeicher übersiehst:

docker compose config --volumes

Keine Volumes zum Test löschen

Verwende für diese Änderung nicht docker compose down -v. Der Parameter -v kann benannte Volumes und damit dauerhafte Anwendungsdaten entfernen.

3. Passenden Healthcheck auswählen

Ein Healthcheck muss eine kleine, lokale und aussagekräftige Prüfung ausführen. Geeignet sind beispielsweise eine interne HTTP-Gesundheitsroute, pg_isready bei PostgreSQL oder ein mit der Anwendung geliefertes Diagnoseprogramm. Docker führt den Befehl regelmäßig aus und unterscheidet dabei die Zustände starting, healthy und unhealthy.[8]

Prüfe zuerst, welches Werkzeug im vorhandenen Image verfügbar ist. Ersetze <dienstname> durch den Namen des zu prüfenden Compose-Dienstes:

docker compose exec <dienstname> sh -c 'command -v curl || command -v wget || true'

<dienstname> steht für den Eintrag direkt unter services: in deiner compose.yaml und muss durch dessen echten Namen ersetzt werden. Eine leere Ausgabe bedeutet, dass weder curl noch wget gefunden wurde. Installiere nicht bei jedem Start ungeprüft zusätzliche Pakete in einem laufenden Container. Nutze stattdessen das Diagnoseprogramm des Images oder baue ein eigenes geprüftes Image mit dem benötigten Werkzeug.

Keine externe Abhängigkeit als allgemeinen Zustandstest verwenden

Prüfe möglichst den lokalen Dienst im selben Container. Eine entfernte Webseite, ein DNS-Dienst oder eine Cloud-API kann ausfallen, obwohl deine Anwendung fehlerfrei arbeitet. Zu breite Prüfungen erzeugen falsche Alarme und können bei automatisierter Reaktion Neustartschleifen auslösen.[6]

4. Healthcheck in Compose ergänzen

Das folgende Muster passt zu einer Anwendung, die im Container auf Port 8080 eine Route /health bereitstellt und bereits curl enthält:

services:
  app:
    image: <vorhandenes-image>
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "--fail", "--silent", "http://localhost:8080/health"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 40s

Ersetze <vorhandenes-image> durch das Image samt Version, das dein Dienst bereits verwendet. Ändere eine vorhandene image:-Zeile nicht nur wegen dieses Beispiels. Passe Port 8080 und Pfad /health an die interne Adresse deiner Anwendung an; der veröffentlichte Host-Port ist für die Prüfung im Container nicht maßgeblich.

Die Werte bedeuten:

  • test führt die lokale Prüfung ohne zusätzliche Shell aus. Exit-Code 0 gilt als erfolgreich, ein anderer Exit-Code als Fehler.[3]
  • interval: 30s startet regulär alle 30 Sekunden eine Prüfung.
  • timeout: 5s bricht eine hängende Einzelprüfung nach fünf Sekunden ab.
  • retries: 3 verlangt drei aufeinanderfolgende Fehlschläge, bevor der Zustand unhealthy wird.
  • start_period: 40s gibt einem langsam startenden Dienst eine Schonzeit, bevor Startfehler auf die Fehlversuche angerechnet werden.[8]
  • restart: unless-stopped startet einen beendeten Container wieder, außer er wurde bewusst gestoppt.[5]

Hat die Anwendung keine passende HTTP-Route, übernimm den Block nicht blind. Für PostgreSQL kann die Prüfung beispielsweise so aussehen:

services:
  db:
    image: postgres:18
    restart: unless-stopped
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
    volumes:
      - db-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
      interval: 10s
      timeout: 10s
      retries: 5
      start_period: 30s

volumes:
  db-data:

POSTGRES_USER, POSTGRES_PASSWORD und POSTGRES_DB müssen in deiner geschützten .env-Datei gesetzt sein. Verwende für POSTGRES_PASSWORD ein starkes eigenes Passwort und veröffentliche die Datei nicht. db-data ist der Name des dauerhaften Volumes und darf bei einer bestehenden Installation nur an deren bisherigen Volumenamen angepasst werden. Das doppelte Dollarzeichen in $${POSTGRES_USER} und $${POSTGRES_DB} verhindert die Auflösung durch Compose auf dem Host; erst die Shell im Container liest die Variablen.

5. Abhängige Dienste auf Bereitschaft warten lassen

Ein kurzes depends_on ordnet nur den Start; Compose wartet dabei nicht automatisch, bis die Anwendung im Container bereit ist. Mit condition: service_healthy wird der abhängige Dienst erst erstellt, nachdem der Healthcheck der Abhängigkeit erfolgreich war.[1]

Ergänze beim abhängigen Anwendungsdienst:

services:
  app:
    image: <app-image>
    restart: unless-stopped
    depends_on:
      db:
        condition: service_healthy
        restart: true

Ersetze <app-image> durch das bereits verwendete Image samt Version. app ist hier der abhängige Dienst, db der Datenbankdienst; passe beide Namen an deine Datei an. restart: true innerhalb von depends_on bedeutet, dass Compose den abhängigen Dienst nach einer ausdrücklich von Compose ausgeführten Aktualisierung oder einem Compose-Neustart der Abhängigkeit ebenfalls neu startet.[1]

Diese restart-Angabe ist nicht dieselbe Eigenschaft wie restart: unless-stopped auf Diensteebene. Sie überwacht auch nicht dauerhaft spätere Healthcheck-Änderungen.

6. Aufgelöste Konfiguration kontrollieren

Lass Compose die vollständige Datei einschließlich Variablen und Standardwerten prüfen:

docker compose config

Kontrolliere in der Ausgabe besonders healthcheck, depends_on, die Dienstnamen und die Volumes. Zeige die für den Start benötigten Images an:

docker compose config --images

Behebe jeden Syntax-, Variablen- oder Imagefehler vor dem nächsten Schritt. Ein gültiges YAML-Dokument beweist noch nicht, dass das Prüfprogramm im Image existiert oder der gewählte Endpunkt richtig antwortet.

7. Dienste geordnet aktualisieren

Übernimm die Änderung im Hintergrund und warte auf laufende beziehungsweise gesunde Dienste:

docker compose up -d --wait

docker compose up erstellt geänderte Container neu und erhält dabei eingebundene Volumes; --wait wartet auf den Zustand running oder healthy und läuft automatisch im Hintergrund.[4] Falls deine Compose-Version --wait nicht kennt, aktualisiere das Compose-Plugin oder starte zunächst ohne diese Option:

docker compose up -d

Prüfe danach den Status separat:

docker compose ps --all

Kurze Unterbrechung einplanen

Geänderte Container können neu erstellt werden. Plane bei produktiven Diensten ein Wartungsfenster ein und prüfe vorher, ob Schreibvorgänge oder Datenbankmigrationen laufen.

8. Healthcheck und Protokoll prüfen

Zeige den Health-Zustand des Dienstes an. Ersetze <containername> durch den tatsächlichen Containernamen aus docker compose ps --all:

docker inspect --format '{{json .State.Health}}' <containername>

docker inspect liefert detaillierte Containerdaten und kann mit --format gezielt einen Teil davon ausgeben.[9] <containername> muss durch den echten Namen oder die Container-ID ersetzt werden. Achte auf Status, FailingStreak, ExitCode und Output.

Zeige zusätzlich die letzten Protokollzeilen des Dienstes. Ersetze <dienstname> wieder durch den Compose-Dienstnamen:

docker compose logs --tail=100 <dienstname>

Rufe die Anwendung anschließend über ihren normalen Browser- oder Client-Zugang auf. Ein grüner Healthcheck ersetzt keinen Test des echten Nutzerwegs.

9. Neustartverhalten sicher testen

Ein Healthcheck allein beendet oder startet einen weiterhin laufenden, aber unhealthy gewordenen Container nicht neu. Restart-Policies reagieren auf beendete Container und auf dokumentierte Docker-Lebenszyklusereignisse, nicht auf den Health-Status allein.[5][6]

Prüfe die konfigurierte Policy. Ersetze <containername> durch den tatsächlichen Namen:

docker inspect --format 'Policy={{.HostConfig.RestartPolicy.Name}} Health={{if .State.Health}}{{.State.Health.Status}}{{else}}nicht-konfiguriert{{end}} Restarts={{.RestartCount}}' <containername>

Teste einen Neustart nur bei einem unkritischen oder zuvor gesicherten Dienst. Ersetze <dienstname> durch seinen Compose-Namen:

docker compose restart <dienstname>

Kontrolliere danach Zustand und Logs:

docker compose ps --all
docker compose logs --tail=100 <dienstname>

Ein höherer Neustartzähler beweist nicht, dass die Anwendung korrekt arbeitet. Prüfe zusätzlich den Health-Status und den normalen Anwendungszugang.[6] Erzwinge für Datenbanken keinen Absturz und töte keine Prozesse, solange du Wiederherstellung und Konsistenz nicht sicher beurteilen kannst.

10. Risiken und Grenzen beachten

  • Ein falscher Prüfpfad oder ein fehlendes Programm kann eine funktionierende Anwendung dauerhaft als unhealthy markieren.
  • Zu kurze Intervalle belasten den Dienst; zu kleine Timeouts und zu wenige Wiederholungen melden normale Lastspitzen als Fehler.
  • Eine Restart-Policy ersetzt keine Ursachenanalyse. Wiederholte Abstürze können Fehler verdecken oder eine Neustartschleife erzeugen.
  • Gesundheitsprüfungen dürfen keine Daten verändern, keine Backups starten und keine externen Kosten auslösen.
  • Gib Datenbank- und Administrationsports nicht allein für einen Healthcheck nach außen frei. Die Prüfung läuft im Container und benötigt normalerweise kein zusätzliches ports:.
  • Hinterlege keine Passwörter, Token oder privaten Schlüssel in test-Befehlen. Sie können über die Containerkonfiguration sichtbar werden.
  • Für wichtige Dienste brauchst du weiterhin Backups und eine externe Überwachung; ein lokaler Healthcheck erkennt weder einen ausgefallenen Host noch einen unterbrochenen Netzwerkweg.

Das öffentlich auffindbare Video „Docker Healthchecks & Restart Policies Explained“ führt Healthchecks und Restart-Policies ergänzend vor.[7] Für technische Entscheidungen sind die aktuellen Docker-Quellen maßgeblich.

11. Typische Fehler beheben

  • unhealthy trotz erreichbarer Anwendung: Lies Output mit docker inspect. Prüfe, ob curl, wget oder das anwendungsspezifische Programm im Image vorhanden ist und ob Port sowie Pfad intern stimmen.
  • docker compose up -d --wait läuft in einen Fehler: Zeige zuerst docker compose ps --all, den Health-Log und die Dienstprotokolle. Erhöhe start_period nur, wenn der Dienst tatsächlich länger startet.
  • Anwendung startet vor der Datenbank: Kontrolliere, ob condition: service_healthy beim richtigen Dienst steht und die Datenbank selbst einen Healthcheck besitzt.[1]
  • Container ist unhealthy, startet aber nicht neu: Das ist bei einem weiterlaufenden Hauptprozess erwartbar. Healthcheck und Restart-Policy sind getrennte Mechanismen.[6]
  • Container bleibt nach manuellem Stoppen aus: unless-stopped respektiert einen bewussten Stopp. Starte ihn wieder mit docker compose up -d.[5]
  • Variablen im PostgreSQL-Check sind leer: Verwende im CMD-SHELL-String $${POSTGRES_USER} statt ${POSTGRES_USER}, damit Compose die Variable nicht vorzeitig auf dem Host ersetzt.
  • Änderung trifft den falschen Stack: Prüfe vor jedem Befehl den aktuellen Ordner und bei Bedarf docker compose ls.

12. Rückweg durchführen

Zeige die angelegten Sicherungen an:

ls -1 compose.yaml.vor-healthcheck-*

Stoppe weitere Tests und kopiere die gewünschte Sicherung zurück. Ersetze <sicherungsdatei> durch den vollständigen Namen aus der vorherigen Ausgabe:

cp <sicherungsdatei> compose.yaml

<sicherungsdatei> steht für den Dateinamen deiner zuvor erstellten Kopie und muss vor dem Ausführen ersetzt werden. Prüfe anschließend die wiederhergestellte Datei:

docker compose config

Übernimm die alte Konfiguration:

docker compose up -d

Prüfe abschließend Status, Protokolle und die Anwendung. Bei beschädigten oder fehlenden Daten reicht die Compose-Sicherung nicht aus; stelle dann das anwendungsspezifische Datenbackup nach dessen dokumentiertem Verfahren wieder her.

Grundlage dieser Anleitung ist die aktuelle offizielle Docker-Anleitung zur Startreihenfolge in Compose, geprüft am 4. September 2026.[1] Ergänzend wurden die Docker-Referenzen zu Healthchecks, docker compose up, Restart-Policies und Diagnosebefehlen sowie eine aktuelle Praxisanalyse von Voxfor geprüft.[3][4][5]

Sources

[1] https://docs.docker.com/compose/how-tos/startup-order — Docker Docs: Control startup and shutdown order in Compose [3] https://docs.docker.com/reference/dockerfile — Docker Docs: Dockerfile reference [4] https://docs.docker.com/reference/cli/docker/compose/up — Docker Docs: docker compose up [5] https://docs.docker.com/engine/containers/start-containers-automatically — Docker Docs: Start containers automatically [6] https://www.voxfor.com/docker-unhealthy-healthcheck-status-restart-policy-main-process-exit — Voxfor: Docker Healthcheck vs Restart Policy [7] https://www.youtube.com/watch?v=CsIZy4mBM5A — YouTube: Docker Healthchecks & Restart Policies Explained [8] https://docs.docker.com/engine/containers/run — Docker Docs: Running containers – Healthchecks [9] https://docs.docker.com/reference/cli/docker/inspect — Docker Docs: docker inspect [10] https://docs.docker.com/reference/cli/docker/compose/ps — Docker Docs: docker compose ps

Fertig

Dein Compose-Projekt besitzt jetzt eine klar definierte Bereitschaftsprüfung, kann abhängige Dienste geordnet starten und beendete Container gemäß der gewählten Restart-Policy erneut starten. Die Funktionsprüfung ist bestanden, wenn docker compose config fehlerfrei endet, docker compose up -d --wait Exit-Code 0 liefert, docker compose ps --all die erwarteten Dienste als laufend und gesund zeigt, der normale Nutzerzugang funktioniert und ein geplanter Neustart ohne Datenverlust abgeschlossen wird.[4][10]