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 wiemkdocs) 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: nofür One-Shot-Container: Migrations (alembic upgrade head), Seed-Scripts (bootstrap-operator-admin), DB-Cleanup-Jobs. Diese sollen nicht auto-restartet werden, sondern explizit perdocker compose runodermake platform-bootstrapgetriggert werden.restart: on-failurewenn 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: alwaysin 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).