# Container shape for the Mode A site (docs/phase-2-static-site.md §2.1). # # Values are fixed by the specification and must not drift: # mem_limit == memswap_limit == 120m so the app cannot eat the host's swap # ports published on 127.0.0.1 only Caddy on .35 is the only public listener # logging capped one bad day cannot fill the disk # # Run it (build the artefacts first — Phase 3's deploy.sh does both): # # make build dist # docker compose -f deploy/compose.yml up -d # # `curl http://127.0.0.1:8096/healthz` must answer with static ready. # The compose project name is deliberately not `ai-resume`: /home/sam/deployment/ # ai-resume on .13 already runs a compose project by that name (backend + db on # the ai-mesh network). Sharing the name would make this site's containers show # up as orphans in that project and vice versa, so anything running `compose # down --remove-orphans` under either project could stop the other. The image # tag stays ai-resume:local (Phase 3 fixes it); only the project namespace is # distinct. name: ai-resume-site services: resume: image: ai-resume:local build: context: .. dockerfile: deploy/Dockerfile restart: unless-stopped mem_limit: 120m memswap_limit: 120m # Published on this host's LAN address, not loopback. Caddy lives on .35 and # proxies to 192.168.20.13:8096, exactly as it does for offsite (:8095), # photo-filter (:8092), garage-ui (:3909) and prefect (:4200). The port is # reachable inside the house only; Caddy on .35 remains the sole public # listener, which is the intent of AGENTS.md section 4. ports: - "192.168.20.13:8096:8096" read_only: true security_opt: - no-new-privileges:true logging: driver: json-file options: max-size: 10m max-file: "3" healthcheck: test: ["CMD", "/usr/bin/resume-server", "--health-check"] interval: 30s timeout: 3s retries: 3 start_period: 5s # The project network gets an explicit, small subnet. The host's docker daemon # has every default address pool allocated by other projects ("all predefined # address pools have been fully subnetted"), so an implicit compose network # cannot be created. Pinning /28 of RFC1918 space that no other bridge or route # on .13 uses keeps this deploy independent of the host's pool exhaustion and # does not touch any other container. Single-service stack: two addresses is # plenty. networks: default: ipam: config: - subnet: 10.89.0.0/28 gateway: 10.89.0.1 # Phase 4/5 add at most three more containers (Qdrant, Prefect worker, query # service) inside the 4-container and 1.0 GiB budget in AGENTS.md §4.3. Mode A # needs none of them and must keep working when they are stopped (test A1).