Reply Pilot Container Runtime Contract
Tento dokument je source of truth pro zmeny v Docker image, Docker Compose a deploy skriptech v repozitari Reply Pilot.
Doplňuje:
docs/remote-server.mdpro server a remote deploy pravidlaAGENTS.mdpro projektove provozni konvence
Vztah k ostatnim artefaktum:
docs/remote-server.mdse porad pouziva pro server a remote deploy pravidla.- Tento dokument drzi projektovy runtime kontrakt pro image, Compose a deploy skripty.
- Codex skill
shift-planner-deploy-runtimeneni source of truth; jen odkazuje na dokumentaci a hlida konzistenci zmen. - Skill se do tohoto repozitare nekopiruje. Codex ho ma nacitat z lokalniho skill adresare
${CODEX_HOME:-$HOME/.codex}/skills/.
Scope
Plati pro vsechny kontejnery provozovane z tohoto repozitare v produkci na mathbox.90.cz,
zejmena pro projekt reply-pilot a dalsi dlouhodobe bezici sluzby pridane do tohoto repozitare.
Neresi:
- aplikacni feature behavior
- HAProxy konfiguraci do detailu
- obsah business logiky aplikace
Repository Layout
Reply Pilot je multi-service repozitar. Kazda dlouhodobe bezici sluzba ma byt samostatny
top-level modul, napriklad reply-pilot-app/, reply-pilot-be/, reply-pilot-gmail/,
reply-pilot-search/, reply-pilot-docs/ nebo reply-pilot-worker/.
Kazdy modul ma obsahovat:
- vlastni
Dockerfile - vlastni
docker-compose.yml - vlastni
.env.example - vlastni
README.md - vlastni
data/,logs/aconf/ - operacni skripty pojmenovane podle modulu:
scripts/<module_name>-start.shscripts/<module_name>-stop.shscripts/<module_name>-deploy.sh
Docker image ma pouzivat stejne jmeno jako modul.
Deployment Dependencies
Nasledujici diagram zachycuje deployment topologii Reply Pilotu. Plne sipky znaci aktualni runtime zavislosti. Prerusovane sipky znaci cilove prime PostgreSQL napojeni, ktere bude doplneno pri dalsim kroku integrace DB do aplikacnich modulu.

Env File Convention
.env.exampleje verzovana sablona vsech podporovanych promennych s vysvetlenim jednotlivych hodnot..env.localje necommitovany lokalni runtime config pro modulovystartskript..env.serverje necommitovany serverovy runtime config pro modulovydeployskript.- Pokud se lokalni nebo serverovy config verzue, ma byt source of truth sifrovany soubor
secrets/<environment>/<module>.envspravovany pressops;.env.locala.env.serverpak vznikaji jen jako lokalni nebo docasne materializovane runtime soubory. startadeployskripty musi nacitat sve env soubory explicitne, ne spolehat na implicitni.env.- Relativni host path v
.envse vyhodnocuji vuci koreni konkretniho modulu, ne vuci aktualnimu shell cwd. - Pokud
HOST_UIDaHOST_GIDnejsou v env souboru nastavene, skript je ma odvodit zid -uaid -g. - Vyjimka je prijatelna jen u vendor-backed image, ktere bez vlastniho entrypoint/runtime modelu nespusti podporovany init flow. Typicky priklad je oficialni PostgreSQL image.
SOPS Access For Another Person
Kdyz ma mit dalsi clovek pristup ke stavajicim sifrovanym secretum:
- Novy clovek si u sebe vygeneruje vlastni age keypair:
mkdir -p ~/.config/sops/age
age-keygen -o ~/.config/sops/age/keys.txt
- Posle jen svuj public key:
age-keygen -y ~/.config/sops/age/keys.txt
- Maintainer prida tenhle public key do
.sops.yamlmezi recipients. - Maintainer rekeyne existujici secrets, aby sly otevrit i novym keypair:
export SOPS_AGE_KEY_FILE="$HOME/.config/sops/age/keys.txt"
sops updatekeys -y secrets/local/*.env secrets/prod/*.env
- Maintainer commitne zmenenou
.sops.yamla rekeynute secrets.
Pravidla:
- public key se sdili bezpecne; private key se nikdy nesdili
- samotny public key neumoznuje decryption
~/.config/sops/age/keys.txtje private keyring, ne public key- kdyz nekdo ztrati pristup, nestaci ho odebrat z
.sops.yaml; je potreba znovu rekeynout files a u citlivych systemu otocit samotne secrets
Rozdeleni odpovednosti
Docker runtime kontrakt neni jen o image. Je rozdelen mezi tri vrstvy:
- Image
- Compose
- 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 aplikacni 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.
- Vendor-backed image mohou mit zdokumentovanou vyjimku z ciziho UID:GID, pokud to vyzaduje jejich oficialni startup sekvence. V takovem pripade je povinna samostatna modulova dokumentace a jasne oddelene host path pro data/logy/conf.
Compose Rules
- Kazda produkcni sluzba = jeden dlouhodobe bezici kontejner.
- Runtime uzivatel se predava pres
HOST_UIDaHOST_GID. - Compose ma explicitne nastavit runtime uzivatele tak, aby proces nebezel jako root.
- Compose patri do konkretniho moduloveho adresare.
- Mounty musi zustat konzistentni s modulovou strukturou:
- data:
/home/agent/docker_deployments/reply-pilot/<module_name>/data->/app/data - logs:
/home/agent/docker_deployments/reply-pilot/<module_name>/logs->/app/logs - conf:
/home/agent/docker_deployments/reply-pilot/<module_name>/conf->/app/conf - Konfiguracni mount
/app/confma byt read-only. - Data mount muze byt read-only, pokud sluzba data jen cte.
- Logs mount musi zustat zapisovatelny runtime uzivatelem.
- Porty na hostu maji byt explicitni a v souladu s deploy dokumentaci.
- Pokud modul publikuje operatorni nebo admin rozhrani na host, defaultni bind ma byt
127.0.0.1, dokud neni zdokumentovany vedomy duvod pro sirejsi vystaveni. - Image name a operacni skripty maji byt pojmenovane stejne jako modul.
- Vyjimka z
HOST_UID/HOST_GIDje dovolena jen pro vendor-backed image, kde by prepsani runtime uzivatele rozbilo podporovany init flow. Takova sluzba musi zustat zdokumentovana jako vyjimka a stale musi drzet bind mounty per modul.
Deploy Script Rules
- Pri remote deployi se
HOST_UIDaHOST_GIDmusi odvodit z uzivatele, pod kterym bezi deploy na serveru: id -uid -g- Modul ma mit vlastni
start,stopadeployskript. startskript ma pouzivat.env.local;deployskript ma pouzivat.env.server.- Pokud se pouziva
sops, start workflow ma pred startem modulu vyrenderovat aktualni.env.localzsecrets/local/<module>.env; kdyz encrypted source of truth chybi, start ma skoncit chybou. - Pokud se pouziva
sops, wrapper nebo operator musi.env.servervyrenderovat pred deployem a po deployi ho zase odstranit. - Deploy skript musi tyto hodnoty predat do
docker compose. - Pred startem musi zajistit existenci potrebnych host adresaru.
- Pokud se objevi root-owned soubory v
data/nebologs/, musi byt ownership srovnan pred dalsim startem. - Pri zmene runtime kontraktu musi deploy skript, compose a dokumentace zustat ve shode.
Standardni Host Paths
- Obecny pattern:
- data:
/home/agent/docker_deployments/reply-pilot/<module_name>/data - logs:
/home/agent/docker_deployments/reply-pilot/<module_name>/logs - conf:
/home/agent/docker_deployments/reply-pilot/<module_name>/conf - Aktualni moduly:
- data:
/home/agent/docker_deployments/reply-pilot/reply-pilot-app/data - logs:
/home/agent/docker_deployments/reply-pilot/reply-pilot-app/logs - conf:
/home/agent/docker_deployments/reply-pilot/reply-pilot-app/conf - data:
/home/agent/docker_deployments/reply-pilot/reply-pilot-be/data - logs:
/home/agent/docker_deployments/reply-pilot/reply-pilot-be/logs - conf:
/home/agent/docker_deployments/reply-pilot/reply-pilot-be/conf - data:
/home/agent/docker_deployments/reply-pilot/reply-pilot-gmail/data - logs:
/home/agent/docker_deployments/reply-pilot/reply-pilot-gmail/logs - conf:
/home/agent/docker_deployments/reply-pilot/reply-pilot-gmail/conf - data:
/home/agent/docker_deployments/reply-pilot/reply-pilot-worker/data - logs:
/home/agent/docker_deployments/reply-pilot/reply-pilot-worker/logs - conf:
/home/agent/docker_deployments/reply-pilot/reply-pilot-worker/conf - data:
/home/agent/docker_deployments/reply-pilot/reply-pilot-search/data - logs:
/home/agent/docker_deployments/reply-pilot/reply-pilot-search/logs - conf:
/home/agent/docker_deployments/reply-pilot/reply-pilot-search/conf - data:
/home/agent/docker_deployments/reply-pilot/reply-pilot-docs/data - logs:
/home/agent/docker_deployments/reply-pilot/reply-pilot-docs/logs - conf:
/home/agent/docker_deployments/reply-pilot/reply-pilot-docs/conf - data:
/home/agent/docker_deployments/reply-pilot/reply-pilot-db/data - logs:
/home/agent/docker_deployments/reply-pilot/reply-pilot-db/logs - conf:
/home/agent/docker_deployments/reply-pilot/reply-pilot-db/conf
Inter-Service Network Contract
- Dlouhodobe bezici Reply Pilot kontejnery se propojuji pres externi Docker sit
reply-pilot-internal. - Sit se vytvari mimo jednotlive compose projekty a jednotlive modulove skripty maji zajistit jeji existenci pred
docker compose up. - Inter-service DNS alias ma odpovidat nazvu modulu, napr.
reply-pilot-be.
Standardni Container Paths
- data:
/app/data - logs:
/app/logs - conf:
/app/conf
Logging Contract
- Kazda dlouhodobe bezici sluzba 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 repozitari, musi vystavovat
GET /healthz. GET /healthzvraci 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 nemacurl - 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.
Ownership Contract
- Host adresare
data/alogs/musi byt zapisovatelne runtime UID:GID. - Kontejner nesmi pri beznem startu vytvaret root-owned soubory v bind mountech.
- Pokud sluzba zapisuje jen do logs, musi stale umet bezet pod non-root uzivatelem.
- Vendor-backed vyjimka je dovolena jen tam, kde image sama spravuje startup ownership a provoz pod vlastnim ne-root uzivatelem.
reply-pilot-dbje tento pripad; data zustavaji v bind mountu, ale ownership uvnitr lifecycle ridi oficialni PostgreSQL image.
Change Checklist
Pri zmene Dockerfile, docker-compose*.yml nebo deploy skriptu zkontroluj vzdy vsechny body:
- Proces v kontejneru opravdu bezi jako non-root.
HOST_UID/HOST_GIDjsou dohledatelne a propisane az do runtime.- Pracujes ve spravnem modulovem adresari a image i skripty jsou pojmenovane podle modulu.
- Mounty odpovidaji
data/,logs/,conf. - Host path odpovida patternu
/home/agent/docker_deployments/reply-pilot/<module_name>/.... confmount zustava read-only.- Sluzba nevytvari root-owned soubory v
data/nebologs/. - Log soubor zustava v
logs/<module_name>.log. - Long-running sluzba ma
restart: unless-stopped. - Health endpoint nebo alternativni health probe odpovida typu sluzby.
- Dokumentace zustava ve shode s implementaci.
Kdy otevrit tento dokument
Otevri tento dokument vzdy, kdyz:
- menis
Dockerfile - menis
docker-compose.ymlnebodocker-compose.dev.yml - menis deploy skript v
scripts/ - resis non-root runtime, ownership nebo mounty
- resis
HOST_UID/HOST_GID