Runbooks, local, Docker & compose
Three ways to run it, verified against the real Dockerfile and compose files, plus the exact health checks each exposes.
Local development runbook
Run the API directly with uvicorn. The source lives under src/, so PYTHONPATH=src is required for a local (non-installed) run; pip install -e . installs the console entry points.
bash
python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e ".[dev]" # core + dev extras
cp .env.example .env # optional; defaults are safe (mock)
# run the API (reload for development)
PYTHONPATH=src uvicorn vailidator.api.routes:app --reload --port 8000
# verify
curl -s http://localhost:8000/health # {"status":"ok","version":"1.4.2"}
- SQLite is created at
<project_root>/vailidator.dbby default (override withDB_PATH). - No API keys needed, the default provider is the offline mock.
- Run the test suite with
python -m pytest tests/ -q.
Docker runbook
The Dockerfile builds a python:3.12-slim image, installs the package, runs as a non-root user (appuser), exposes 8000, ships a container HEALTHCHECK, and launches uvicorn with a single worker.
bash
docker build -f Dockerfile -t verifaier-api . docker run --rm -p 8000:8000 \ --env-file .env \ -e DB_PATH=/app/data/vailidator.db \ -v verifaier_data:/app/data \ verifaier-api curl -s http://localhost:8000/health
/app/data inside the container, mount a volume there (as above) or the data is lost when the container is removed. See backup posture.- Workers: the image runs
--workers 1. Scale by running more replicas behind a load balancer (SQLite is single-writer, for true multi-node, useDATABASE_URLPostgres). - Non-root: the process runs as
appuser;/app/datais owned by it.
docker-compose runbook
docker-compose.yml brings up the API plus the two Streamlit dashboards. The dashboards wait for the API to be healthy before starting; the API's SQLite lives on the named db_data volume and reads .env via env_file.
bash
# production-style stack (api :8000, dashboard :8501, cc_dashboard :8502) docker compose up --build # development: live code reload + local ./data + ./src mounts docker compose -f docker-compose.yml -f docker-compose.dev.yml up --build docker compose ps # check health docker compose logs -f api docker compose down # keep the db_data volume docker compose down -v # DESTROY the db_data volume (data loss)
| Service | Image | Port | Depends on |
|---|---|---|---|
api | Dockerfile | 8000 | n/a |
dashboard | Dockerfile.dashboard | 8501 | api healthy |
cc_dashboard | Dockerfile.cc_dashboard | 8502 | api healthy |
The dashboards reach the API via API_URL=http://api:8000 (set by compose). All services use restart: unless-stopped.
Health checks
Every runtime exposes a liveness endpoint, and the containers wire it into their HEALTHCHECK:
| Target | Check | Container HEALTHCHECK |
|---|---|---|
| API | GET /health → {"status":"ok","version":"1.4.2"} | urllib GET /health, 30s interval, 5s timeout, 3 retries, 15s start-period |
| dashboard | Streamlit /_stcore/health | urllib GET, 30s interval, 20s start-period |
| cc_dashboard | Streamlit /_stcore/health | urllib GET, 30s interval, 20s start-period |
/health is unauthenticated and dependency-free, safe for load balancers and uptime probes. Use it for readiness and liveness. For deeper checks, see the authenticated monitoring endpoints.