#!/bin/bash # Single-container entrypoint (docs/DECISIONS.md D16). Two responsibilities: # # 1. Run migrations before serving anything. There's no separate "run migrations, then start the # app" step in front of this container the way docs/PLAN.md's original deploy.yml had one for # the 3-container Postgres stack (see apps/api/Dockerfile's history) — a single container has # nowhere else to put that step. `set -e` means a failed migration exits non-zero here, which # still fails startup visibly (Docker/Unraid shows the container as exited/restarting) instead # of silently serving a broken app; that's the property the separate step existed to protect, # preserved by a different mechanism now that there's only one container to do it in. # 2. Run uvicorn and Caddy as two background processes and tie their lifetimes together: if either # one dies, kill the other and exit with its status, so Docker/Unraid restarts the whole # container. Two half-alive processes (API up, web serving stale/nothing, or vice versa) is a # worse failure mode than a clean restart. set -euo pipefail alembic -c /app/alembic.ini upgrade head # uvicorn binds loopback only — Caddy is the sole process with an exposed port, and the sole # thing that talks to uvicorn (see deploy/Caddyfile's reverse_proxy target). uvicorn velodrome.app:app --host 127.0.0.1 --port 8000 & API_PID=$! caddy run --config /etc/caddy/Caddyfile --adapter caddyfile & CADDY_PID=$! trap 'kill -TERM "$API_PID" "$CADDY_PID" 2>/dev/null || true' TERM INT wait -n "$API_PID" "$CADDY_PID" EXIT_CODE=$? kill -TERM "$API_PID" "$CADDY_PID" 2>/dev/null || true exit "$EXIT_CODE"