Zum Inhalt

Restart-Policies pro Service

Konvention seit K-Q4-Fix-B.3: restart: unless-stopped ist der Default für alle Long-Lived-Services. One-Shots (Migrations, Seed-Scripts) bleiben auf restart: no.

Warum unless-stopped und nicht always

Policy Verhalten Wann sinnvoll
unless-stopped Auto-Restart auf Crash + nach Reboot, respektiert manuelles docker stop / make kora-down Default für alle Long-Lived-Services
always Auto-Restart auch nach manuellem Stop — der Container kommt immer zurück, bis die Policy geändert wird Selten gewollt; bricht reproduzierbares Operator-Verhalten
on-failure Restart nur bei non-zero Exit Produktion-Worker mit klarem Crash-Signal
no Kein Auto-Restart One-Shots (migrate, seed, bootstrap)

unless-stopped ist der goldene Mittelweg: ein Operator, der Probleme diagnostiziert, kann einen Service mit make kora-restart SVC=<svc> neu starten oder mit docker stop <name> stoppen — ohne dass der Container im Hintergrund still wieder hochkommt.

Service-Tabelle

docker-compose.platform.yml (kora-platform)

Alle 12 Services sind auf unless-stopped. Stand seit K-Q4-Fix-B.1.

Service Policy Anmerkung
postgres unless-stopped Haupt-DB
qdrant unless-stopped Vector-DB
redis unless-stopped Cache + Semantic-Cache
keycloak-db unless-stopped Auth-DB
keycloak unless-stopped IdP
mailhog unless-stopped Dev-Mail-Catcher
api unless-stopped FastAPI
embedder unless-stopped BGE-M3
reranker unless-stopped Cross-Encoder
scheduler unless-stopped Ofelia (Cron-Replacement)
mkdocs unless-stopped Static-Docs-Server
demo-frontend unless-stopped Showcase-Nginx

docker-compose.yml (Demo-Stack, K-Q4-Fix-B.3 harmonisiert)

12 Long-Lived-Services. Vorher gemischt (always für Auth/GPU-Exporter, gar keine Policy für Postgres/Redis/Qdrant/MinIO/API/Nginx/Prometheus/Grafana).

Tabelle bewusst aggregiert (nicht per-Service wie oben). Der Demo-Stack ist homogen support-orientiert — alle Services sind Long-Lived und nutzen dieselbe Policy. Per-Service-Auflistung wäre redundant; Gruppierung nach Migrations-Pfad (B.3-ergänzt vs. von-always-harmonisiert vs. bewusste Sonderfälle wie mkdocs) ist informativer. Im Platform-Stack oben ist die per-Service-Form gewählt, weil dort die Service-Rollen heterogener sind (DB / Cache / Vector-DB / Auth / API / Embedder / Reranker / …).

Service Policy Anmerkung
qdrant, postgres, redis, minio, api, nginx, prometheus, grafana unless-stopped B.3 ergänzt (waren ohne Policy)
nvidia-gpu-exporter, keycloak-db, keycloak unless-stopped B.3 von always harmonisiert
mkdocs unless-stopped (bewusst) Dev-Server, läuft auf der Demo-Box bewusst dauerhaft als Live-Doku-Server (docs.avs.luki-net.org). KEIN Profile-Move nach dev-Profil, weil die Demo-Box demo+prod gleichzeitig spielt. Bei reinem Prod-Setup würde der Service in ein dev-only-Profil wandern.

One-Shots gibt es im Demo-Stack nicht (Migrations laufen via make platform-*- Wrapper aus docker compose run, nicht als persistenter Compose-Service).

Wann ist eine Abweichung sinnvoll?

  • restart: no für One-Shot-Container: Migrations (alembic upgrade head), Seed-Scripts (bootstrap-operator-admin), DB-Cleanup-Jobs. Diese sollen nicht auto-restartet werden, sondern explizit per docker compose run oder make platform-bootstrap getriggert werden.
  • restart: on-failure wenn ein Worker beim Erfolg sauber mit Exit 0 aussteigen darf (z.B. ein lang laufender Batch-Job, der bei Crash neu starten soll, aber bei sauberem Exit nicht).
  • restart: always in Sonderfällen, wo absoluter Auto-Restart-Zwang gewollt ist (selten — meistens ein Symptom von kaputter Liveness-Probe- Logik, die man stattdessen fixen sollte).

Verifikation

# Aktuelle Policy aller Container im kora-Project:
for c in $(docker compose -p kora-platform -f docker-compose.platform.yml \
             --env-file .env.platform ps -q); do
  printf "%-45s %s\n" \
    "$(docker inspect "$c" --format '{{.Name}}' | sed 's|^/||')" \
    "$(docker inspect "$c" --format '{{.HostConfig.RestartPolicy.Name}}')"
done

Erwartung: jede Zeile endet mit unless-stopped (oder no für explizit-One-Shot-Container, falls vorhanden).