# resume — runtime container (Phase 3 §3.2). # # Copied into each release directory by deploy/deploy.sh; the release's .env # supplies APP_VERSION (the image tag). Never edited on the host — change it # here, in git, and deploy again. # # Limits that are not negotiable (AGENTS.md §4.3): # mem_limit == memswap_limit == 120m -> the container cannot touch host swap # ports never 0.0.0.0 -> Caddy on .35 is the only public listener # # Published on two explicit addresses and nothing else (Sam, 2026-10-26, on # AUD-133: "A - dual bind: 127.0.0.1:8096 and 192.168.20.13:8096"): # 127.0.0.1 -> deploy.sh health gate and local checks on .13 # 192.168.20.13 -> the LAN address Caddy on .35 proxies to (phase doc §3.3) # A wildcard bind is still forbidden; if APP_LAN_IP is unset the LAN address # defaults to this host's own 192.168.20.13. # # .13 has every default Docker address pool subnetted out (many projects), so a # single-container service uses the host bridge and publishes its port rather # than creating a project network. Same pattern as compass-teams-nhs. name: resume services: app: image: resume/app:${APP_VERSION} container_name: resume-app restart: unless-stopped network_mode: bridge ports: - "127.0.0.1:${APP_PORT:-8096}:8096" - "${APP_LAN_IP:-192.168.20.13}:${APP_PORT:-8096}:8096" environment: PORT: "8096" APP_VERSION: "${APP_VERSION}" # Mode B values arrive in Phase 5 from ~/.config/environment.d/ — never here. mem_limit: 120m memswap_limit: 120m logging: driver: json-file options: max-size: "10m" max-file: "3" healthcheck: test: ["CMD", "wget", "-qO-", "http://127.0.0.1:8096/healthz"] interval: 30s timeout: 5s retries: 3 start_period: 5s