Shift Planner Container Runtime Contract

Tento dokument je source of truth pro zmeny v Docker image, Docker Compose a deploy skriptech v repozitari Shift Planner.

Doplňuje:

  • docs/remote-server.md pro server/deploy pravidla
  • AGENT.md pro projektove provozni konvence

Vztah k ostatnim artefaktum:

  • docs/remote-server.md se porad pouziva pro server a remote deploy pravidla.
  • Tento dokument drzi jen projektovy runtime kontrakt pro image, Compose a deploy skripty.
  • Codex skill pro deploy/runtime workflow neni source of truth; jen odkazuje na dokumentaci a hlida konzistenci zmen.
  • Zdroj skillu muze byt verzovany v repu pod codex-skills/, ale Codex ho realne nacita az z lokalniho skill adresare ${CODEX_HOME:-$HOME/.codex}/skills/.

Scope

Plati pro moduly, ktere bezí jako kontejnery v produkci na mathbox.90.cz:

  • shift-planner-app
  • shift-planner-jobs
  • shift-planner-waha
  • shift-planner-doc
  • cme-authentication-mock

Neřeší:

  • aplikační feature behavior
  • HAProxy konfiguraci do detailu
  • CME business logiku

Rozdeleni odpovednosti

Docker runtime kontrakt neni jen o image. Je rozdělen mezi tri vrstvy:

  1. Image
  2. Compose
  3. Deploy skript

Kazda z nich musi dodrzet svou cast. Zmena jen v jedne vrstve je podezrela a musi byt vedoma.

Image Rules

  • Aplikacni proces v kontejneru musi umet bezet jako non-root uzivatel.
  • Image nesmi vyzadovat root-only operace pri beznem startu aplikace.
  • Image musi pouzivat stabilni aplikačni cesty pod /app.
  • Aplikace musi zapisovat jen do adresaru, ktere jsou pro to urcene mounty nebo internim tmp adresarem.
  • Pokud image potrebuje inicializaci souboru nebo adresaru, musi byt kompatibilni s cizim numerickym UID:GID predanym z runtime.

Compose Rules

  • Produkcni modul = jeden dlouhodobe bezici kontejner.
  • Runtime uzivatel se predava pres HOST_UID a HOST_GID.
  • Compose ma explicitne nastavit runtime uzivatele tak, aby proces nebezel jako root.
  • Mounty musi zustat konzistentni s projektovou strukturou:
  • data: /home/agent/shift-planner/data -> /app/data
  • logs: /home/agent/shift-planner/logs -> /app/logs
  • conf: /home/agent/shift-planner/conf -> /app/conf
  • Konfiguracni mount /app/conf ma byt read-only.
  • Data mount muze byt read-only, pokud modul data jen cte.
  • Logs mount musi zustat zapisovatelny runtime uzivatelem.
  • Porty na hostu maji byt explicitni a v souladu s deploy dokumentaci.

Deploy Script Rules

  • Pri remote deployi se HOST_UID a HOST_GID musi odvodit z uzivatele, pod kterym bezi deploy na serveru:
  • id -u
  • id -g
  • Deploy skript musi tyto hodnoty predat do docker compose.
  • Pred startem musi zajistit existenci potrebnych host adresaru.
  • Deploy skript nesmi kopirovat ani prepisovat runtime konfiguraci v /home/agent/shift-planner/conf.
  • Bind-mounted conf/ je server-managed runtime stav; deploy ma pouze overit, ze pozadovane soubory a povinne klice na serveru existuji.
  • Pokud se objevi root-owned soubory v data/ nebo logs/, musi byt ownership srovnan pred dalsim startem.
  • Pri zmene runtime kontraktu musi deploy skript, compose a dokumentace zustat ve shode.

Standardni Host Paths

  • data: /home/agent/shift-planner/data
  • logs: /home/agent/shift-planner/logs
  • conf: /home/agent/shift-planner/conf

Standardni Container Paths

  • data: /app/data
  • logs: /app/logs
  • conf: /app/conf

Logging Contract

  • Kazdy modul zapisuje aktivni log do logs/<module_name>.log.
  • Rotace probiha po 100 MB.
  • Rotovane soubory maji format <module_name>.0001.log, <module_name>.0002.log, ...
  • Aktivni log po rotaci zustava <module_name>.log.

Monitoring Contract

  • Kazda dlouhodobe bezici produkcni sluzba musi mit restart: unless-stopped.
  • HTTP sluzby, ktere spravujeme v tomto repu, musi vystavovat GET /healthz.
  • GET /healthz vraci JSON:
  • healthy: 200 {"status":"ok"}
  • unhealthy: 503 {"status":"unhealthy","reason":"..."}
  • Compose ma mit healthcheck vsude, kde je to technicky rozumne.
  • Probe v healthchecku je service-specific:
  • nepouzivej slepe curl, pokud image nema curl
  • pro Python image je v poradku probe pres python
  • pro ne-HTTP sluzby je v poradku heartbeat nebo process-based probe
  • Pokud jde o third-party image, je prijatelny vendor-specific endpoint nebo zdokumentovana vyjimka.
  • shift-planner-jobs je scheduler, ne HTTP sluzba; preferovany probe je heartbeat-based healthcheck.

Ownership Contract

  • Host adresare data/ a logs/ musi byt zapisovatelne runtime UID:GID.
  • Kontejner nesmi pri beznem startu vytvaret root-owned soubory v bind mountech.
  • Pokud modul zapisuje jen do logs, musi stale umet bezet pod non-root uzivatelem.

Change Checklist

Pri zmene Dockerfile, docker-compose*.yml nebo deploy skriptu zkontroluj vzdy vsechny body:

  1. Proces v kontejneru opravdu bezi jako non-root.
  2. HOST_UID/HOST_GID jsou dohledatelne a propisane az do runtime.
  3. Mounty odpovidaji data/, logs/, conf.
  4. conf mount zustava read-only.
  5. Modul nevytvari root-owned soubory v data/ nebo logs/.
  6. Log soubor zustava v logs/<module_name>.log.
  7. Long-running sluzba ma restart: unless-stopped.
  8. Health endpoint nebo alternativni health probe odpovida typu sluzby.
  9. Dokumentace zustava ve shode s implementaci.

Kdy otevrit tento dokument

Otevri tento dokument vzdy, kdyz:

  • menis Dockerfile
  • menis docker-compose.yml nebo docker-compose.dev.yml
  • menis deploy skript v scripts/
  • resis non-root runtime, ownership nebo mounty
  • resis HOST_UID/HOST_GID