Files
ai-resume/deploy/compose.yml
Sam Rolfe f39f560c7f deploy: publish on the LAN address so Caddy on .35 can reach it
127.0.0.1:8096 is unreachable from .35, which is where Caddy runs. Every other
service on .13 is published this way (8095, 8092, 3909, 4200) and proxied by the
same Caddy. Port is LAN-only; Caddy remains the sole public listener.
2026-10-26 22:40:24 +11:00

72 lines
2.8 KiB
YAML

# 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).