Zum Inhalt springen
myvpsguide

Healthchecks und Restart-Regeln in Compose: was sie leisten und was nicht

Die vier Restart-Regeln, ein Healthcheck, der wirklich etwas prüft, Startreihenfolge mit depends_on und der verbreitete Irrtum, dass Docker ungesunde Container neu startet.

veröffentlicht 19.09.2026
4 min lesezeit
fortgeschritten

Zwei Einstellungen in einer Compose-Datei entscheiden, was passiert, wenn etwas schiefgeht: restart und healthcheck. Beide sind schnell eingetragen und werden oft falsch verstanden. Der häufigste Irrtum: Ein Container, den Docker als „unhealthy“ markiert, würde automatisch neu gestartet. Das tut Docker ohne Swarm nicht.

Die vier Restart-Regeln#

services:
  app:
    image: meine-app:1.4
    restart: unless-stopped
RegelStartet neu, wenn …Nach Neustart des Hosts
nonienein
on-failure[:n]der Prozess mit Fehlercode endet (höchstens n-mal)für Dienste nicht darauf bauen
alwaysder Prozess endet, egal wieja, auch wenn du ihn gestoppt hattest
unless-stoppedder Prozess endet, außer du hast ihn gestopptja, außer du hast ihn gestoppt

Für Dienste ist unless-stopped fast immer die richtige Wahl. Mit always kommt ein Container, den du bewusst gestoppt hast, nach dem nächsten Neustart des Hosts zurück, und das ist selten gewollt. on-failure passt zu Aufgaben, die fertig werden sollen, etwa einer Migration beim Start.

Docker wartet zwischen den Versuchen immer länger, damit eine Neustartschleife den Host nicht lahmlegt. Ob ein Container in einer Schleife hängt, zeigt docker ps in der Spalte STATUS („Restarting“) und docker inspect -f '{{.RestartCount}}' app.

Ein Healthcheck, der etwas prüft#

Ein Container kann laufen und trotzdem nichts tun: Der Prozess hängt, die Datenbankverbindung ist weg, der Speicher voll. Der Healthcheck fragt regelmäßig nach:

services:
  app:
    image: meine-app:1.4
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-fsS", "http://localhost:8080/health"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 60s
  • test: ein Befehl im Container. Rückgabewert 0 heißt gesund. curl -f liefert bei HTTP-Fehlern einen Fehlercode.
  • retries: erst nach drei Fehlschlägen in Folge gilt der Container als unhealthy. Ein einzelner langsamer Moment löst nichts aus.
  • start_period: in dieser Zeit nach dem Start zählen Fehlschläge nicht mit, damit eine langsam startende Anwendung nicht sofort als krank gilt.

Das Werkzeug muss im Image sein. Viele schlanke Images haben weder curl noch wget. Dann bringt die Anwendung eine eigene Prüfung mit, oder du nutzt, was da ist, etwa pg_isready bei PostgreSQL oder redis-cli ping:

  db:
    image: postgres:17
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER}"]
      interval: 10s
      retries: 5

Das doppelte $$ verhindert, dass Compose die Variable selbst ersetzt; sie wird erst im Container ausgewertet.

Was „gesund“ prüfen sollte#

Ein guter Endpunkt /health prüft, was die Anwendung zum Arbeiten braucht: Datenbank erreichbar, Platte beschreibbar. Er sollte aber nicht von fremden Diensten abhängen. Fällt ein externer Zahlungsanbieter aus, hilft es nichts, wenn deine Anwendung sich deshalb für krank erklärt und neu gestartet wird.

Startreihenfolge mit depends_on#

services:
  app:
    depends_on:
      db:
        condition: service_healthy
  db:
    image: postgres:17
    healthcheck: …

Ohne condition wartet Compose nur, bis der Datenbank-Container gestartet ist, nicht bis PostgreSQL Verbindungen annimmt. Mit service_healthy wartet es auf den ersten erfolgreichen Healthcheck. Das verhindert die klassische Fehlermeldung „connection refused“ beim ersten Start.

Das gilt nur beim Start durch docker compose up. Startet die Datenbank später neu, weiß die Anwendung nichts davon; sie muss mit einer verlorenen Verbindung selbst umgehen können.

Der Irrtum: unhealthy heißt nicht Neustart#

Docker startet ungesunde Container nicht neu

Die Restart-Regel greift, wenn der Prozess endet. Ein Container, der läuft, aber als unhealthy markiert ist, bleibt einfach so stehen. Nur im Swarm-Modus ersetzt Docker ungesunde Container. Mit Compose auf einem einzelnen Server siehst du den Zustand, und sonst passiert nichts.

Drei Wege, damit trotzdem etwas geschieht:

  1. Überwachen und melden. Ein Monitoring, das den Zustand abfragt und dich benachrichtigt, zum Beispiel Uptime Kuma. Du entscheidest dann selbst.
  2. Die Anwendung beendet sich selbst. Merkt sie, dass sie nicht mehr arbeiten kann, beendet sie sich mit Fehlercode, und die Restart-Regel greift. Das ist die sauberste Lösung, wenn du die Anwendung kontrollierst.
  3. Ein Wächter-Container wie autoheal, der ungesunde Container anhand eines Labels neu startet. Er braucht Zugriff auf den Docker-Socket, und damit faktisch root-Rechte auf dem Host. Wäge das bewusst ab.

Den Zustand sehen#

docker compose ps                                  # Spalte STATUS zeigt (healthy)/(unhealthy)
docker inspect --format '{{json .State.Health}}' app | jq

Die zweite Zeile zeigt die letzten Prüfergebnisse samt Ausgabe des Test-Befehls. Dort steht meist, warum der Container als ungesund gilt.

Häufige Fragen#

Wie oft sollte der Healthcheck laufen?#

30 Sekunden sind für die meisten Dienste genug. Jede Prüfung startet einen Prozess im Container; bei vielen Containern mit kurzen Abständen summiert sich das.

Kann ein Healthcheck schaden?#

Ja, wenn er teuer ist, etwa eine aufwendige Datenbankabfrage alle fünf Sekunden. Oder wenn er zu streng ist und bei kurzer Last einen gesunden Dienst als krank meldet. retries und timeout großzügig wählen.

Brauche ich das auch für Datenbanken?#

Gerade dort, weil andere Container mit depends_on darauf warten. PostgreSQL, MariaDB und Redis bringen passende Prüfwerkzeuge mit.

Was ist mit Kubernetes?#

Dort gibt es getrennte Prüfungen für „lebt“ und „ist bereit“, und ungesunde Container werden tatsächlich ersetzt. Ob sich das für dich lohnt, steht in k3s auf dem VPS.

Kurz gesagt#

  • restart: unless-stopped für Dienste, on-failure für Aufgaben.
  • Ein Healthcheck braucht ein Prüfwerkzeug im Image und eine start_period.
  • depends_on mit condition: service_healthy wartet, bis die Datenbank wirklich bereit ist.
  • Docker startet unhealthy Container ohne Swarm nicht neu.
  • Also: überwachen und melden, oder die Anwendung beendet sich selbst.
MRMedia

Geschrieben aus dem laufenden Betrieb: MRMedia betreibt eigene Proxmox- Hosts, einen Backup-Server und Kundendienste in der EU. Fehler in einer Anleitung sind Fehler im eigenen Betrieb. Korrekturen bitte über Discord.