WIRELESS_REGISTRATIONS stream had a 256MB MaxBytes cap in a 256MB container — guaranteed to crash under load. ALERT_EVENTS and OPERATION_EVENTS had no byte limit at all. - Reduce WIRELESS_REGISTRATIONS MaxBytes from 256MB to 128MB - Add 16MB MaxBytes cap to ALERT_EVENTS and OPERATION_EVENTS - Bump NATS container memory limit from 256MB to 384MB - Add restart: unless-stopped to NATS in base compose - Bump version to 9.8.2 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
190 lines
4.8 KiB
YAML
190 lines
4.8 KiB
YAML
# ─── Low-RAM build note ──────────────────────────────────────────────────────
|
|
# On a 2-core / 2-4 GB server, build images ONE AT A TIME to avoid OOM:
|
|
#
|
|
# docker compose build api
|
|
# docker compose build poller
|
|
# docker compose build frontend
|
|
#
|
|
# Running `docker compose build` (all at once) will trigger three concurrent
|
|
# multi-stage builds (Go, Python/pip, Node/tsc/Vite) that together can peak at
|
|
# 3-4 GB RAM, crashing the machine before any image finishes.
|
|
#
|
|
# Once built, starting the stack uses far less RAM (nginx + uvicorn + Go binary).
|
|
# ─────────────────────────────────────────────────────────────────────────────
|
|
|
|
services:
|
|
postgres:
|
|
image: timescale/timescaledb:2.17.2-pg17
|
|
container_name: tod_postgres
|
|
environment:
|
|
POSTGRES_DB: ${POSTGRES_DB:-tod}
|
|
POSTGRES_USER: ${POSTGRES_USER:-postgres}
|
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres}
|
|
ports:
|
|
- "5432:5432"
|
|
volumes:
|
|
- ./docker-data/postgres:/var/lib/postgresql/data
|
|
- ./scripts/init-postgres.sql:/docker-entrypoint-initdb.d/init.sql:ro
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U postgres -d ${POSTGRES_DB:-tod}"]
|
|
interval: 5s
|
|
timeout: 5s
|
|
retries: 5
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 512M
|
|
networks:
|
|
- tod
|
|
|
|
redis:
|
|
image: redis:7-alpine
|
|
container_name: tod_redis
|
|
ports:
|
|
- "6379:6379"
|
|
volumes:
|
|
- ./docker-data/redis:/data
|
|
healthcheck:
|
|
test: ["CMD", "redis-cli", "ping"]
|
|
interval: 5s
|
|
timeout: 3s
|
|
retries: 5
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 128M
|
|
networks:
|
|
- tod
|
|
|
|
nats:
|
|
image: nats:2-alpine
|
|
container_name: tod_nats
|
|
command: ["--jetstream", "--store_dir", "/data", "-m", "8222"]
|
|
ports:
|
|
- "4222:4222"
|
|
- "8222:8222"
|
|
volumes:
|
|
- ./docker-data/nats:/data
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "wget --spider -q http://localhost:8222/healthz || exit 1"]
|
|
interval: 5s
|
|
timeout: 5s
|
|
retries: 5
|
|
restart: unless-stopped
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 384M
|
|
networks:
|
|
- tod
|
|
|
|
openbao:
|
|
image: openbao/openbao:2.1
|
|
container_name: tod_openbao
|
|
entrypoint: /bin/sh
|
|
command:
|
|
- -c
|
|
- |
|
|
bao server -config=/etc/openbao/config.hcl &
|
|
BAO_PID=$$!
|
|
sleep 2
|
|
/init/init.sh
|
|
wait $$BAO_PID
|
|
environment:
|
|
BAO_ADDR: "http://127.0.0.1:8200"
|
|
BAO_UNSEAL_KEY: "${BAO_UNSEAL_KEY:-}"
|
|
BAO_TOKEN: "${OPENBAO_TOKEN:-}"
|
|
ports:
|
|
- "8200:8200"
|
|
volumes:
|
|
- ./infrastructure/openbao/config.hcl:/etc/openbao/config.hcl:ro
|
|
- ./infrastructure/openbao/init.sh:/init/init.sh:ro
|
|
- openbao_data:/openbao/data
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:8200/v1/sys/health | grep -q '\"sealed\":false' || exit 1"]
|
|
interval: 5s
|
|
timeout: 3s
|
|
retries: 12
|
|
start_period: 30s
|
|
restart: unless-stopped
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 256M
|
|
networks:
|
|
- tod
|
|
|
|
wireguard:
|
|
image: lscr.io/linuxserver/wireguard:latest
|
|
container_name: tod_wireguard
|
|
environment:
|
|
- PUID=1000
|
|
- PGID=1000
|
|
- TZ=UTC
|
|
volumes:
|
|
- ./docker-data/wireguard:/config
|
|
- ./docker-data/wireguard/custom-cont-init.d:/custom-cont-init.d
|
|
ports:
|
|
- "51820:51820/udp"
|
|
cap_add:
|
|
- NET_ADMIN
|
|
sysctls:
|
|
- net.ipv4.ip_forward=1
|
|
- net.ipv4.conf.all.src_valid_mark=1
|
|
restart: unless-stopped
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "ip link show wg0 2>/dev/null || exit 0"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 3
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 128M
|
|
networks:
|
|
- tod
|
|
|
|
mailpit:
|
|
image: axllent/mailpit:latest
|
|
profiles: ["mail-testing"]
|
|
ports:
|
|
- "8026:8025"
|
|
- "1026:1025"
|
|
networks:
|
|
- tod
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 64M
|
|
|
|
winbox-worker:
|
|
build:
|
|
context: ./winbox-worker
|
|
platform: linux/amd64
|
|
container_name: tod_winbox_worker
|
|
environment:
|
|
IDLE_TIMEOUT: 600
|
|
MAX_LIFETIME: 7200
|
|
MAX_CONCURRENT_SESSIONS: 10
|
|
LOG_LEVEL: info
|
|
XDG_RUNTIME_DIR: /run/user/1001
|
|
ports:
|
|
- "10100-10119:10100-10119"
|
|
deploy:
|
|
resources:
|
|
limits:
|
|
memory: 1G
|
|
networks:
|
|
- tod
|
|
- tod_remote_worker
|
|
|
|
volumes:
|
|
openbao_data:
|
|
|
|
networks:
|
|
tod:
|
|
driver: bridge
|
|
tod_remote_worker:
|
|
driver: bridge
|
|
internal: true
|