Add local dev Docker stack
backend/Dockerfile and a root docker-compose.yml for running flask-api, bettersight-worker, bettersight-redis, and firecrawl locally — needed to exercise the dashboard against a real backend instead of mocks. Firecrawl and PocketBase are gated behind opt-in compose profiles since self-hosted Firecrawl builds from source (slow) and PocketBase is typically run separately in dev. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
d4f2c7d96b
commit
f848b9f15a
|
|
@ -0,0 +1,23 @@
|
|||
FROM python:3.12-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# System deps for Playwright's Chromium (playwright install-deps covers the
|
||||
# actual browser dependencies below; git/curl are just useful in-container
|
||||
# for debugging import/dependency issues without rebuilding).
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
curl \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY requirements.txt .
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# Installs the Chromium binary + the OS-level libraries it needs
|
||||
# (fonts, codecs, etc.) — must run after playwright is pip-installed.
|
||||
RUN playwright install --with-deps chromium
|
||||
|
||||
COPY . .
|
||||
|
||||
EXPOSE 5000
|
||||
|
||||
CMD ["gunicorn", "app:app", "-w", "4", "-b", "0.0.0.0:5000"]
|
||||
|
|
@ -0,0 +1,163 @@
|
|||
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
|
||||
Loading…
Reference in New Issue