networks: bettersight_default: # LOCAL DEV — CLAUDE.md §4 uses an external `pangolin_default` network # (Dokploy/Pangolin-managed, production only). Locally there is no # Pangolin reverse proxy, so this is a plain compose-managed bridge # network instead. Do not port this network block to production — # production still uses the external pangolin_default per CLAUDE.md. driver: bridge volumes: pocketbase_data: services: flask-api: build: ./backend container_name: flask-api command: gunicorn app:app -w 4 -b 0.0.0.0:5000 env_file: ./backend/.env environment: # Overrides backend/.env's values with container-network-correct # addresses. host.docker.internal reaches the PocketBase instance # already running on the host machine (per user instruction, that # instance is started manually and is NOT the pocketbase service # below — this compose file never starts its own PocketBase). - POCKETBASE_URL=http://host.docker.internal:8090 - REDIS_URL=redis://bettersight-redis:6379 - FIRECRAWL_URL=http://firecrawl-api:3002 ports: - "5050:5000" extra_hosts: - "host.docker.internal:host-gateway" networks: - bettersight_default restart: unless-stopped depends_on: - bettersight-redis bettersight-worker: build: ./backend container_name: bettersight-worker command: rq worker high normal low -u redis://bettersight-redis:6379 env_file: ./backend/.env environment: - POCKETBASE_URL=http://host.docker.internal:8090 - REDIS_URL=redis://bettersight-redis:6379 - FIRECRAWL_URL=http://firecrawl-api:3002 extra_hosts: - "host.docker.internal:host-gateway" networks: - bettersight_default restart: unless-stopped depends_on: - bettersight-redis bettersight-redis: image: redis:alpine container_name: bettersight-redis networks: - bettersight_default restart: unless-stopped # ── Opt-in only — real self-hosted Firecrawl is a 3-service stack # built from source (no stable published image — see CLAUDE.md §4's # "Firecrawl — real self-hosted stack" note). The build is slow # (playwright-service alone pulls in Chromium + fonts), and Firecrawl # is only used for on-demand /v1/map trip-intent matching — not # required for viewing dashboard pages. Start explicitly with # `docker compose --profile firecrawl up -d` when trip-intent # matching needs to be exercised locally. firecrawl-api: build: context: https://github.com/firecrawl/firecrawl.git#main dockerfile: apps/api/Dockerfile container_name: firecrawl-api profiles: ["firecrawl"] environment: - PORT=3002 - HOST=0.0.0.0 - REDIS_URL=redis://bettersight-redis:6379 - REDIS_RATE_LIMIT_URL=redis://bettersight-redis:6379 - PLAYWRIGHT_MICROSERVICE_URL=http://firecrawl-playwright:3000/scrape - USE_DB_AUTHENTICATION=false - NUM_WORKERS_PER_QUEUE=8 depends_on: - bettersight-redis - firecrawl-playwright networks: - bettersight_default restart: unless-stopped firecrawl-worker: build: context: https://github.com/firecrawl/firecrawl.git#main dockerfile: apps/api/Dockerfile container_name: firecrawl-worker profiles: ["firecrawl"] command: pnpm run workers environment: - REDIS_URL=redis://bettersight-redis:6379 - REDIS_RATE_LIMIT_URL=redis://bettersight-redis:6379 - PLAYWRIGHT_MICROSERVICE_URL=http://firecrawl-playwright:3000/scrape - USE_DB_AUTHENTICATION=false depends_on: - bettersight-redis - firecrawl-playwright networks: - bettersight_default restart: unless-stopped firecrawl-playwright: build: context: https://github.com/firecrawl/firecrawl.git#main dockerfile: apps/playwright-service-ts/Dockerfile container_name: firecrawl-playwright profiles: ["firecrawl"] environment: - PORT=3000 networks: - bettersight_default restart: unless-stopped mem_limit: 4g # ── Opt-in only — excluded from a plain `docker compose up -d` ──────── # Started with `docker compose --profile with-pocketbase up -d # pocketbase` if this local host-run instance is ever retired in # favour of a containerized one. Per explicit instruction: defined # here for parity with CLAUDE.md §4, but never auto-started while a # host PocketBase is already running on localhost:8090. pocketbase: image: ghcr.io/muchobien/pocketbase:latest container_name: pocketbase profiles: ["with-pocketbase"] volumes: - pocketbase_data:/pb_data - ./backend/pb_migrations:/pb_migrations networks: - bettersight_default restart: unless-stopped # ── Opt-in only — needs MAIL_FROM/SMTP config not present locally ── freescout: image: freescout/freescout:latest container_name: freescout profiles: ["support"] environment: - APP_URL=http://localhost:8080 - MAIL_FROM=support@bettersight.io networks: - bettersight_default restart: unless-stopped # ── Opt-in only — needs Hetzner S3 credentials not present locally ── litestream: image: litestream/litestream:latest container_name: litestream profiles: ["backup"] command: replicate environment: - LITESTREAM_ACCESS_KEY_ID=${HETZNER_S3_ACCESS_KEY} - LITESTREAM_SECRET_ACCESS_KEY=${HETZNER_S3_SECRET_KEY} networks: - bettersight_default restart: unless-stopped