Docker Compose Healthchecks helfen dir, den Zustand deiner Container genauer zu beurteilen. Ein Container kann bereits laufen, obwohl die Datenbank noch startet oder der Webdienst keine brauchbaren Antworten liefert. Mit einer passenden Prüfung erkennt Docker solche Situationen und zeigt zusätzlich zum Containerstatus einen Gesundheitszustand an.

In diesem Praxisbeispiel betreibst du einen kleinen Webdienst zusammen mit PostgreSQL. Die Datenbank erhält einen eigenen Healthcheck. Der Webdienst startet erst, wenn diese Prüfung erfolgreich ist. Anschließend kontrolliert sein Healthcheck regelmäßig, ob eine HTTP-Anfrage einschließlich einer einfachen Datenbankabfrage funktioniert.

Gestartet, gesund und tatsächlich nutzbar: die Unterschiede

Beim Prüfen eines Compose-Projekts solltest du drei Ebenen auseinanderhalten:

Ebene Was sie aussagt Beispiel
Container läuft Der Hauptprozess des Containers läuft. Docker zeigt beispielsweise running oder Up an. PostgreSQL wurde gestartet, initialisiert aber noch seine Daten.
Container ist gesund Der konfigurierte Healthcheck war erfolgreich. Seine Aussage hängt vom verwendeten Prüfverfahren ab. Der Datenbankserver nimmt Verbindungsversuche entgegen.
Anwendung ist tatsächlich nutzbar Die benötigten Funktionen arbeiten über den vorgesehenen Zugriffsweg. Benutzer können sich anmelden und vorhandene Datensätze lesen oder speichern.

Ein erfolgreicher HTTP-Aufruf auf eine statische Startseite sagt beispielsweise wenig über die Datenbankverbindung aus. Ebenso kann ein interner Healthcheck erfolgreich sein, während ein falsch konfigurierter Reverse Proxy den Zugriff von außen verhindert.

Wähle deshalb eine Prüfung, die zu deinem Dienst passt. Nach Updates gehört zusätzlich ein kurzer Funktionstest der eigentlichen Anwendung dazu.

Wie Docker Compose Healthchecks ausführt

Ein Healthcheck ist ein Befehl, den Docker innerhalb des betreffenden Containers ausführt. Die Prüfung verwendet dessen Programme, Dateisystem, Netzwerkzugriff und Benutzerrechte.

Für eigene Prüfprogramme sind zwei Rückgabewerte vorgesehen:

  • 0: Die Prüfung war erfolgreich.
  • 1: Die Prüfung ist fehlgeschlagen.

Der Rückgabewert 2 ist für Docker-Healthchecks reserviert. Liefert ein verwendetes Werkzeug eigene Fehlercodes, kannst du diese im Prüfkommando auf 1 vereinheitlichen.

Bei einem laufenden Container mit Healthcheck begegnen dir diese Zustände:

  • starting: Die Prüfung hat die Startbereitschaft noch nicht bestätigt.
  • healthy: Die Prüfung war erfolgreich.
  • unhealthy: Die festgelegte Anzahl aufeinanderfolgender Fehlversuche wurde erreicht.

Ein einzelner Fehlschlag führt bei mehreren erlaubten Fehlversuchen noch nicht zu unhealthy. Umgekehrt genügt eine erfolgreiche Prüfung, damit ein ungesunder Container wieder als healthy gilt. Ohne konfigurierten Healthcheck gibt es keinen entsprechenden Gesundheitsnachweis.

Die Einstellungen test, interval, timeout, retries und start_period

Die folgenden Angaben stehen unter healthcheck: beim jeweiligen Compose-Dienst:

Einstellung Beispiel Bedeutung
test ["CMD", "python", "/app/healthcheck.py"] Legt das Prüfprogramm und seine Argumente fest.
interval 10s Bestimmt im regulären Betrieb den Abstand vom Ende einer Prüfung bis zum Beginn der nächsten.
timeout 5s Begrenzt die Laufzeit einer einzelnen Prüfung. Eine Überschreitung zählt als Fehlschlag.
retries 3 Legt fest, wie viele aufeinanderfolgende Fehlversuche den Zustand unhealthy auslösen.
start_period 20s Gewährt eine Anlaufphase, in der anfängliche Fehlschläge noch nicht auf den Fehlerzähler angerechnet werden.

CMD und CMD-SHELL unterscheiden

Mit CMD startet Docker das Programm direkt. Jedes Argument ist ein eigener Listeneintrag:

healthcheck:
  test: ["CMD", "python", "/app/healthcheck.py"]

Shell-Funktionen wie Variablen-Ersetzung, Pipes oder || stehen dabei nicht zur Verfügung.

Mit CMD-SHELL führt Docker den angegebenen Text über die Standardshell des Containers aus. Bei den hier verwendeten Linux-Images ist das normalerweise /bin/sh. Diese Form verwenden wir später für PostgreSQL, um Umgebungsvariablen auszulesen und Fehlercodes zu vereinheitlichen.

start_period ist keine feste Wartezeit

Während der Anlaufphase finden bereits Prüfungen statt. Wird eine davon erfolgreich abgeschlossen, kann der Container sofort healthy werden. Weitere Fehlschläge werden dann auch innerhalb der ursprünglich vorgesehenen Anlaufzeit gezählt.

Du musst daher keine lange Startverzögerung einbauen, nur weil eine Datenbank gelegentlich etwas länger braucht. start_period schützt vor einer vorschnellen Fehlermeldung beim Anlaufen.

Der Prüfabstand während dieser Phase lässt sich auf aktuellen Docker-Versionen zusätzlich über start_interval beeinflussen. Für die folgenden Beispiele ist keine eigene Einstellung dafür erforderlich.

retries beendet die Überwachung nicht

Bei retries: 3 hört Docker nach drei Fehlversuchen nicht auf. Es setzt den Zustand auf unhealthy und prüft weiter. Eine erfolgreiche Prüfung setzt den Fehlerzähler zurück.

Aus interval: 10s und retries: 3 ergibt sich außerdem keine exakt garantierte Erkennungszeit von 30 Sekunden. Der Zeitpunkt des Ausfalls und die Laufzeit der einzelnen Prüfungen kommen hinzu.

Die genaue Bedeutung der Optionen beschreibt die Docker-Referenz zu HEALTHCHECK.

Praxisbeispiel: Webdienst mit PostgreSQL

Du benötigst eine funktionierende Docker Engine und eine aktuelle Docker-Compose-Version. Unter Docker Desktop müssen Linux-Container aktiviert sein. Falls Docker noch fehlt, hilft dir die Anleitung zur Installation und Konfiguration von Docker.

Prüfe zunächst, ob die Engine erreichbar ist und Compose zur Verfügung steht:

docker version
docker compose version

Lege für das Beispiel einen neuen Projektordner mit dieser Struktur an:

healthcheck-demo/
├── compose.yaml
├── .env
└── web/
    ├── Dockerfile
    ├── app.py
    └── healthcheck.py

Der Webdienst verwendet für die Demonstration Pythons http.server. Für einen produktiven Webdienst verwendest du einen dafür geeigneten Anwendungsserver. Auch der Datenbankzugriff sollte dann über einen eigenen Benutzer mit den tatsächlich benötigten Rechten erfolgen.

1. Passwort in der .env-Datei hinterlegen

Erstelle im Projektordner die Datei .env. Ersetze den Beispielwert durch ein eigenes langes Passwort:

POSTGRES_PASSWORD='HierEinEigenesLangesPasswortEintragen'

Compose liest diesen Wert für die Variablen-Ersetzung ein. An die Container wird er anschließend ausdrücklich über environment: weitergegeben. Veröffentliche die Datei nicht mit echten Zugangsdaten in einem öffentlichen Repository.

2. Den Webdienst anlegen

Speichere folgenden Inhalt als web/app.py:

import os
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer

import psycopg


class Handler(BaseHTTPRequestHandler):
    def respond(self, status, text):
        body = text.encode("utf-8")
        self.send_response(status)
        self.send_header("Content-Type", "text/plain; charset=utf-8")
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        self.wfile.write(body)

    def do_GET(self):
        if self.path == "/":
            self.respond(
                200,
                "Webdienst läuft. Datenbankprüfung unter /health\n",
            )
            return

        if self.path != "/health":
            self.respond(404, "Nicht gefunden\n")
            return

        try:
            with psycopg.connect(
                host="db",
                port=5432,
                dbname=os.environ["POSTGRES_DB"],
                user=os.environ["POSTGRES_USER"],
                password=os.environ["POSTGRES_PASSWORD"],
                connect_timeout=2,
                options="-c statement_timeout=2000",
                autocommit=True,
            ) as connection:
                connection.execute("SELECT 1").fetchone()
        except psycopg.Error:
            self.respond(503, "Datenbank nicht bereit\n")
            return

        self.respond(200, "ok\n")


if __name__ == "__main__":
    ThreadingHTTPServer(("0.0.0.0", 8000), Handler).serve_forever()

Der Dienst stellt zwei unterschiedliche Antworten bereit:

  • / bestätigt, dass der Webdienst HTTP-Anfragen beantworten kann.
  • /health öffnet zusätzlich eine Datenbankverbindung und führt SELECT 1 aus. Nur bei Erfolg kommt HTTP 200 zurück. Bei einem Datenbankfehler antwortet der Dienst mit HTTP 503.

Die Datenbank wird unter dem Compose-Dienstnamen db angesprochen. localhost wäre an dieser Stelle falsch: Innerhalb des Webcontainers verweist es auf den Webcontainer selbst.

Die Prüfung bestätigt damit auch den Netzwerkzugriff und die Anmeldung mit den konfigurierten Zugangsdaten. Sie kontrolliert jedoch weder ein bestimmtes Anwendungsschema noch Schreibrechte oder fachliche Abläufe. Dafür müsste der Prüfpfad gezielt erweitert werden.

3. Das Prüfprogramm erstellen

Speichere diesen Inhalt als web/healthcheck.py:

import sys
from urllib.error import URLError
from urllib.request import urlopen


try:
    with urlopen(
        "http://127.0.0.1:8000/health",
        timeout=4,
    ) as response:
        if response.status != 200:
            print(f"Unerwarteter HTTP-Status: {response.status}")
            sys.exit(1)
except (URLError, TimeoutError) as error:
    print(f"Healthcheck fehlgeschlagen: {error}")
    sys.exit(1)

sys.exit(0)

Python behandelt eine HTTP-Fehlerantwort wie 503 hier als Fehler. Das Programm endet dann mit dem Rückgabewert 1. Dasselbe gilt bei einer nicht erreichbaren HTTP-Schnittstelle oder einer Zeitüberschreitung.

Das Prüfprogramm nutzt die Python-Standardbibliothek. Im Webimage werden deshalb weder curl noch wget benötigt.

4. Das Webimage beschreiben

Erstelle die Datei web/Dockerfile:

FROM python:3.13-slim

WORKDIR /app

RUN pip install --no-cache-dir "psycopg[binary]>=3.2,<4"

COPY app.py healthcheck.py ./

USER 10001:10001

CMD ["python", "-u", "app.py"]

psycopg übernimmt den PostgreSQL-Zugriff. Die Variante psycopg[binary] bringt auf unterstützten Plattformen die benötigten Binärkomponenten mit. Einzelheiten beschreibt die Psycopg-Installationsanleitung.

5. Die Compose-Datei erstellen

Speichere im Projektordner folgende compose.yaml:

name: healthcheck-demo

services:
  db:
    image: postgres:18
    environment:
      POSTGRES_DB: appdb
      POSTGRES_USER: appuser
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?Bitte POSTGRES_PASSWORD in .env setzen}
    volumes:
      - db_data:/var/lib/postgresql
    restart: unless-stopped
    healthcheck:
      test:
        - CMD-SHELL
        - 'pg_isready -h 127.0.0.1 -U "$${POSTGRES_USER}" -d "$${POSTGRES_DB}" -t 2 || exit 1'
      interval: 10s
      timeout: 3s
      retries: 5
      start_period: 30s

  web:
    build: ./web
    environment:
      POSTGRES_DB: appdb
      POSTGRES_USER: appuser
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?Bitte POSTGRES_PASSWORD in .env setzen}
    ports:
      - "127.0.0.1:8080:8000"
    depends_on:
      db:
        condition: service_healthy
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "python", "/app/healthcheck.py"]
      interval: 10s
      timeout: 5s
      retries: 3
      start_period: 20s

volumes:
  db_data:

Der Webdienst wird am Docker-Host ausschließlich über 127.0.0.1:8080 veröffentlicht. Die Datenbank benötigt für die Kommunikation zwischen den Diensten keine Portfreigabe auf dem Host.

Das Beispiel verwendet das offizielle PostgreSQL-18-Image. Dort wird das Datenvolume unter /var/lib/postgresql eingebunden. Bei PostgreSQL 17 und älteren Hauptversionen verwendet das offizielle Image standardmäßig einen anderen Volume-Zielpfad. Beachte dazu die Hinweise zum PostgreSQL-Datenverzeichnis.

Warum im Datenbank-Healthcheck doppelte Dollarzeichen stehen

$${POSTGRES_USER} verhindert, dass Compose den Ausdruck schon beim Einlesen der YAML-Datei ersetzt. Im Container erhält die Shell daraus ${POSTGRES_USER} und liest den Wert aus dessen Umgebung.

Das unterscheidet sich von ${POSTGRES_PASSWORD:?...} unter environment:: Dieser Ausdruck wird von Compose aufgelöst. Fehlt der Wert oder ist er leer, bricht die Konfigurationsverarbeitung mit der angegebenen Meldung ab.

Diese beiden Ebenen erklärt die Docker-Dokumentation zur Variablen-Ersetzung.

Was pg_isready tatsächlich prüft

pg_isready ist im verwendeten PostgreSQL-Image enthalten und prüft, ob der Datenbankserver Verbindungen annimmt. Mit -h 127.0.0.1 erfolgt die Prüfung ausdrücklich über TCP. Dadurch wird beim ersten Initialisieren nicht bereits der vorübergehend gestartete, nur über Unix-Sockets erreichbare PostgreSQL-Server als bereit gewertet.

Die Prüfung bestätigt keine erfolgreiche Anmeldung mit dem Anwendungspasswort. Laut PostgreSQL-Dokumentation zu pg_isready sind korrekte Benutzer-, Passwort- und Datenbankangaben für die reine Statusermittlung nicht erforderlich.

Deshalb führt der Webdienst zusätzlich seine eigene SQL-Abfrage aus. Erst diese kontrolliert den Zugriff mit den tatsächlich verwendeten Zugangsdaten. Der Zusatz || exit 1 vereinheitlicht fehlgeschlagene Aufrufe von pg_isready auf den Docker-Fehlercode 1.

Mit service_healthy auf die Datenbank warten

Eine einfache Abhängigkeit wie diese regelt die Startreihenfolge:

depends_on:
  - db

Sie wartet darauf, dass der Datenbankcontainer gestartet wurde. Ob PostgreSQL schon Verbindungen annehmen kann, wird dabei nicht geprüft.

Das vollständige Beispiel verwendet deshalb die lange Schreibweise:

depends_on:
  db:
    condition: service_healthy

Compose wartet damit beim Start des abhängigen Dienstes auf einen erfolgreichen Healthcheck der Datenbank. Fehlt der Datenbank-Healthcheck oder wird die Voraussetzung nicht erfüllt, kann Compose den vorgesehenen Startablauf nicht erfolgreich abschließen.

Diese Abhängigkeit ist keine dauerhafte Überwachung mit automatischer Folgereaktion. Fällt die Datenbank später aus, stoppt Compose den bereits laufenden Webdienst dadurch nicht. Die Anwendung muss Verbindungsabbrüche selbst behandeln und Verbindungen wieder aufbauen können.

Im Beispiel wird bei jeder Anfrage an /health eine neue Verbindung geöffnet. Dadurch kann die Prüfung nach einer Rückkehr der Datenbank wieder erfolgreich werden. Bei produktiven Anwendungen sind dafür häufig Wiederholungsversuche mit Wartezeiten und ein geeignetes Verbindungsmanagement nötig.

Weitere Beispiele findest du in der Docker-Anleitung zur Startreihenfolge mit Compose.

Das Compose-Projekt starten und den Status prüfen

Führe im Projektordner zunächst die Konfigurationsprüfung aus:

docker compose config --quiet

Bei erfolgreicher Prüfung bleibt die Ausgabe normalerweise leer. Anschließend baust und startest du das Projekt:

docker compose up -d --build --wait --wait-timeout 120

--wait wartet bei Diensten mit Healthcheck auf healthy. Bei Diensten ohne Healthcheck genügt der laufende Zustand. --wait-timeout 120 begrenzt diese Wartephase auf 120 Sekunden. Die Optionen beschreibt die Referenz zu docker compose up.

Öffne danach auf dem Docker-Host beziehungsweise bei lokalem Docker Desktop diese Adressen:

Bei einem entfernten Docker-Host beziehen sich diese Loopback-Adressen auf den entfernten Rechner. Für den Browserzugriff benötigst du dann beispielsweise einen passenden SSH-Tunnel.

Containerstatus und Anwendungsprotokolle anzeigen

docker compose ps
docker compose ps --all
docker compose logs --tail=100 db web

Achte bei den laufenden Diensten auf Zusätze wie healthy, health: starting oder unhealthy. Mit --all werden auch gestoppte Container sichtbar.

Für eine maschinenlesbare Ausgabe kannst du zusätzlich JSON verwenden:

docker compose ps --format json

Darin stehen der Prozesszustand und der Gesundheitszustand in getrennten Feldern: State und Health. Die verfügbaren Ausgaben erläutert die Dokumentation zu docker compose ps.

Die Ergebnisse der einzelnen Healthchecks lesen

Die Ausgabe des Prüfprogramms findest du über docker inspect. In Bash, beispielsweise unter Linux oder WSL, funktioniert das so:

docker inspect --format '{{json .State.Health}}' "$(docker compose ps -q web)"

In PowerShell kannst du die Container-ID zuerst in einer Variablen speichern:

$webContainer = docker compose ps -q web
docker inspect --format '{{json .State.Health}}' $webContainer

Interessant sind besonders diese Angaben:

  • Status: aktueller Gesundheitszustand.
  • FailingStreak: Anzahl aufeinanderfolgender gewerteter Fehlversuche.
  • Log: zuletzt gespeicherte Prüfergebnisse mit Zeitangaben, Rückgabewert und Ausgabe.

Die Healthcheck-Ausgabe ist vom normalen Anwendungsprotokoll getrennt. Eine Meldung des Prüfprogramms muss deshalb nicht unter docker compose logs erscheinen. Docker speichert außerdem nur eine begrenzte Historie; für längerfristige Auswertungen benötigst du Monitoring.

Die Prüfprogramme manuell ausführen

Diese Befehle helfen bei der Fehlersuche:

docker compose exec web python /app/healthcheck.py
docker compose exec db pg_isready -h 127.0.0.1 -U appuser -d appdb -t 2

Damit prüfst du im jeweiligen Container, ob der Aufruf grundsätzlich funktioniert. Ein manueller Aufruf verändert den von Docker geführten Gesundheitszustand nicht direkt. Dafür zählt die nächste reguläre Healthcheck-Ausführung.

Einen Datenbankausfall nachvollziehen

Im eigens angelegten Demoprojekt kannst du beobachten, wie sich ein späterer Ausfall auswirkt. Stoppe dazu die Datenbank:

docker compose stop db

Der Webdienst läuft weiter. Seine Startseite unter / bleibt erreichbar, weil sie keine Datenbankverbindung benötigt. Der Prüfpfad /health liefert dagegen HTTP 503.

Nachdem die erforderlichen aufeinanderfolgenden Fehlversuche gezählt wurden, wechselt der Webcontainer zu unhealthy. Das geschieht zeitversetzt entsprechend den Prüfintervallen und Laufzeiten.

Kontrolliere den Zustand mit:

docker compose ps --all

Starte anschließend die Datenbank wieder:

docker compose start db

Sobald PostgreSQL wieder erreichbar ist und die nächste Webprüfung erfolgreich durchläuft, erhält der Webcontainer wieder den Zustand healthy. Ein Neustart des Webdienstes ist für dieses Beispiel nicht erforderlich.

Was macht Docker bei einem ungesunden Container?

Bei einem gewöhnlichen Docker-Compose-Projekt löst der Zustand unhealthy allein keinen automatischen Neustart aus.

Docker aktualisiert den Gesundheitszustand, speichert die jüngsten Prüfergebnisse und erzeugt bei einem Zustandswechsel ein health_status-Ereignis. Die Prüfungen laufen weiter. Der Hauptprozess wird wegen dieses Status nicht automatisch beendet, und veröffentlichte Ports werden dadurch nicht automatisch gesperrt.

Auch die Einstellung aus dem Beispiel ändert daran nichts:

restart: unless-stopped

Eine solche Neustartrichtlinie betrifft das Beenden beziehungsweise erneute Starten von Containern. Ein Healthcheck-Fehler beendet zunächst nur das Prüfprogramm mit einem Fehlercode. Solange der eigentliche Containerprozess weiterläuft, wird durch die Richtlinie kein Neustart ausgelöst.

Überschreitet die Prüfung ihr timeout, beendet Docker den Prüfprozess. Das ist ebenfalls kein Neustart des Anwendungsprozesses.

Davon zu unterscheiden ist restart: true innerhalb einer langen depends_on-Definition. Diese Compose-Option betrifft das erneute Starten abhängiger Dienste bei bestimmten ausdrücklich durch Compose gesteuerten Änderungen oder Neustarts. Sie ist keine Reaktion auf einen späteren Wechsel zu unhealthy.

Wenn auf einen Gesundheitsfehler automatisch reagiert werden soll, brauchst du eine ausdrücklich dafür eingerichtete Überwachung oder einen passenden Orchestrator. Lege vorher fest, ob eine Benachrichtigung, ein Neustart oder eine andere Maßnahme sinnvoll ist. Bei einer nicht erreichbaren Datenbank beseitigt ein wiederholter Neustart des Webdienstes die Ursache meist nicht.

Diese Beschreibung bezieht sich auf normale Compose-Container. Docker-Swarm-Services besitzen eine eigene Aufgabenverwaltung und können auf fehlgeschlagene Healthchecks anders reagieren. Die allgemeinen Container-Neustartrichtlinien erklärt die Docker-Dokumentation zum automatischen Starten von Containern.

Typische Healthcheck-Fehler und ihre Ursachen

curl oder wget fehlt im Container

Eine häufige Ursache für unhealthy ist ein Prüfprogramm, das im Image gar nicht vorhanden ist. In den Prüfergebnissen erscheinen dann beispielsweise Meldungen wie curl: not found oder executable file not found.

Ob curl auf deinem Docker-Host installiert ist, spielt dabei keine Rolle. Der Healthcheck läuft im Container.

Du hast zwei naheliegende Möglichkeiten:

  • Verwende ein bereits vorhandenes Programm, wie Python im Webdienst dieses Artikels.
  • Ergänze das benötigte Prüfwerkzeug dauerhaft im Dockerfile des Images.

Wenn du beim hier verwendeten Debian-basierten Python-Image ausdrücklich curl nutzen möchtest, kannst du vor der Zeile USER diesen Build-Schritt ergänzen:

RUN apt-get update \
    && apt-get install -y --no-install-recommends curl \
    && rm -rf /var/lib/apt/lists/*

Für Alpine-basierte Images wäre ein anderer Paketmanager nötig. Besonders kleine Images können auch ganz ohne Shell oder Paketmanager ausgeliefert werden. Prüfe deshalb die Grundlage deines Images.

Eine passende alternative Prüfung mit curl wäre:

healthcheck:
  test: ["CMD", "curl", "--fail", "--silent", "--show-error", "--max-time", "4", "http://127.0.0.1:8000/health"]
  interval: 10s
  timeout: 5s
  retries: 3
  start_period: 20s

--fail sorgt dafür, dass HTTP-Fehlerantworten einen Fehlercode auslösen. --max-time begrenzt den Aufruf innerhalb des etwas größeren Docker-Timeouts. Details stehen im curl-Handbuch.

Baue das Image nach einer Dockerfile-Änderung neu und lasse Compose die Änderung anwenden:

docker compose up -d --build

Eine manuelle Paketinstallation in einem laufenden Container ist keine dauerhafte Lösung: Beim Ersetzen des Containers geht diese Änderung verloren.

Der Healthcheck verwendet den falschen Port

Im Beispiel lautet die Portzuordnung 8080:8000. Auf dem Host verwendest du Port 8080. Innerhalb des Webcontainers hört die Anwendung auf Port 8000.

Der interne Healthcheck muss deshalb http://127.0.0.1:8000/health aufrufen. Port 8080 wäre innerhalb dieses Containers der falsche Zielport.

Eine Fehlerseite wird als Erfolg gewertet

Ein Prüfwerkzeug muss einen fehlgeschlagenen Anwendungstest mit einem passenden Prozess-Rückgabewert melden. Eine ausgegebene HTTP-Fehlerseite allein genügt Docker nicht.

Vermeide außerdem Shell-Konstruktionen wie || true am Ende der Prüfung. Sie können Fehler verdecken, weil der Gesamtbefehl trotzdem erfolgreich endet.

Die Prüfung verlangt eine Shell, aber CMD wurde verwendet

Bei CMD werden Variablen wie $POSTGRES_USER nicht durch eine Shell ersetzt. Auch || exit 1 funktioniert dort nicht als Shell-Anweisung.

Verwende für solche Ausdrücke CMD-SHELL oder verschiebe die Logik in ein eigenes Prüfprogramm. Bei Images ohne Shell ist die direkte Ausführung eines vorhandenen Programms erforderlich.

Die Datenbank ist healthy, aber der Webdienst bleibt unhealthy

Das kann im Beispiel ein hilfreicher Hinweis sein: PostgreSQL nimmt Verbindungen an, aber der Zugriff aus der Anwendung scheitert. Prüfe Benutzername, Passwort, Datenbankname und die Ausgaben unter .State.Health.

Beachte bei einem bereits gefüllten PostgreSQL-Volume: Eine Änderung von POSTGRES_PASSWORD in der Compose-Konfiguration ändert nicht automatisch das vorhandene Datenbankpasswort. Die Initialisierungsvariablen des offiziellen Images wirken beim Anlegen eines leeren Datenverzeichnisses. Eine spätere Passwortänderung muss in der Datenbank selbst erfolgen.

Die Startphase ist zu kurz oder die Prüfung zu teuer

Benötigt ein Dienst beim ersten Start länger, kontrolliere seine Protokolle und passe gegebenenfalls start_period an. Ein höheres timeout sollte zu einer tatsächlich benötigten Prüfdauer passen.

Halte den Prüfpfad kurz und möglichst ohne Nebenwirkungen. Vollständige Berichte, umfangreiche Tabellenabfragen oder externe Dienste mit langen Antwortzeiten eignen sich dafür schlecht. Wenn du Schema oder Berechtigungen mitprüfst, verwende eine kleine, gezielte Operation.

Healthchecks nach Änderungen und Updates verwenden

Änderst du die Healthcheck-Konfiguration in compose.yaml, wende sie mit docker compose up -d an. Ein einfaches docker compose restart übernimmt eine geänderte Containerkonfiguration nicht. Bei Änderungen am Webimage gehört der erneute Build dazu.

Gerade nach Updates ist ein gesunder Container ein hilfreicher erster Kontrollpunkt. Teste danach trotzdem den Zugriff über die tatsächliche Adresse und eine wichtige Anwendungsfunktion. Der Artikel Docker Compose aktualisieren: Images, Volumes und Rollback beschreibt den dazu passenden Wartungsablauf.

Wenn du Compose-Projekte zentral verwaltest, kannst du die Healthchecks zusammen mit den übrigen Diensteinstellungen pflegen. Wie du bestehende Projekte einbindest und welche Dateien auf dem Zielhost verfügbar sein müssen, erklärt die Anleitung Docker-Stacks in Dockhand importieren und remote verwalten.

Checkliste für aussagekräftige Healthchecks

  • Prüfe eine Funktion, die für die Bereitschaft des Dienstes relevant ist.
  • Stelle sicher, dass das Prüfprogramm im Container vorhanden und ausführbar ist.
  • Verwende innerhalb des Containers dessen internen Port.
  • Lass das Prüfprogramm Erfolg und Fehler über eindeutige Rückgabewerte melden.
  • Wähle Intervall, Timeout und Anlaufphase passend zum Dienst.
  • Nutze service_healthy, wenn ein abhängiger Dienst auf einen erfolgreichen Healthcheck warten soll.
  • Behandle spätere Verbindungsabbrüche in der Anwendung.
  • Plane ausdrücklich, wer auf unhealthy reagiert.
  • Ergänze interne Prüfungen um externe Erreichbarkeits- und Anwendungstests.

Werbung / Affiliate-Links: Die mit einem Sternchen (*) gekennzeichneten Links sind Amazon-Partnerlinks. Wenn du darüber etwas kaufst, erhalte ich möglicherweise eine Provision. Für dich entstehen dadurch keine zusätzlichen Kosten. Als Amazon-Partner verdiene ich an qualifizierten Verkäufen.

Weiterführende Informationen