Files
parking_solution/docker-compose.prod.yml
T
julian c637b2783c feat(deploy): Caddy reverse proxy — clean port-80 URL, server internal
Operators/admins reach the booth at http://<name-or-ip>/ (no :3000). Adds a caddy:2-alpine
proxy to the prod override that reverse-proxies :80 → server:3000 (the /api/ws WebSocket
upgrades pass through natively); the server is now `expose: 3000` (internal, no published
port), vision stays internal. The Caddyfile binds `:80` so it matches ANY hostname/IP —
works for the booth IP, localhost, AND parksystems.msai.al (pointed at the booth via
hosts/DNS on-site; no domain baked into any image). TLS later = swap `:80` for the real
hostname + uncomment :443 → Caddy auto-provisions HTTPS.

Pairs with the relative-/api SPA fix (77b2acb): together verified end-to-end locally —
through Caddy on :80 with Host: parksystems.msai.al, GET / serves the SPA, assets/health
200, and POST /api/auth/login reaches the server (real 401, no CORS/connection error).

Claude-Session: https://claude.ai/code/session_01Xcm6ikLgGoCxxHrxtjkk5V
2026-06-23 19:15:23 +02:00

60 lines
1.9 KiB
YAML

# PROD override: pull pinned registry images (no local build), restart always, real
# recognizer, and a CADDY reverse proxy in front so operators reach the booth on a clean
# port-80 URL (no :3000) — and a path to real TLS later. Server + vision stay INTERNAL
# (only Caddy publishes a port). Use with the base file and pin TAG to the branch you deploy:
# REGISTRY=git.infra.msai.al/mca/parking_solution TAG=main \
# docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
# See wiki/decisions/container-deployment.md.
services:
# Reverse proxy: :80 → server:3000 (WebSocket /api/ws upgrades pass through natively).
# Caddy is a single static binary with a one-line proxy config; swapping http:// for the
# site's real hostname later enables automatic HTTPS. The booth is reached at
# http://<name-or-ip>/ (the name set via hosts/DNS on-site — NOT baked into any image).
proxy:
image: caddy:2-alpine
restart: always
ports:
- "80:80"
# - "443:443" # uncomment when moving to TLS (and set a real hostname in Caddyfile)
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy-data:/data
- caddy-config:/config
depends_on:
- server
networks:
- parking
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
server:
restart: always
# No published port — only the proxy reaches the server, over the private network.
expose:
- "3000"
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
vision:
restart: always
# The real ANPR engine. The image baked the model weights at build (offline-first).
environment:
VISION_RECOGNIZER: fast_alpr
# No published ports — vision is reached only by the server over the private network.
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
volumes:
caddy-data:
caddy-config: