docker-compose.yml
Rama main · réplica de lectura del repositorio original.
# Dev stack: frontend (nginx) + backend (uvicorn --reload, source bind-mounted)
# + the hunter (the agent daemon). Postgres is NOT here — every service uses
# the existing LAN DB (DATABASE_URL in each .env, kept out of the images by
# .dockerignore). The Playwright MCP the agent drives is external too
# (PLAYWRIGHT_MCP_URL in agent/.env) and must run with --isolated: the daemon
# opens one browser context per job.
#
# docker compose up --build # frontend http://localhost:8081, API http://localhost:8000
# docker compose --profile vision up --build # + the visual-authenticity sidecar (:8100) and its minio
# # (image bytes persist in the minio-data volume,
# # DINOv3 weights cache in vision-hf-cache)
#
# Editing backend/app/** hot-reloads inside the container. Changing
# requirements.txt (or frontend/agent code) needs a rebuild: docker compose up --build.
services:
backend:
build: ./backend
env_file: backend/.env
ports:
- "8000:8000" # also lets `npm run dev` (Vite proxy) hit the containerized API
# Dev overrides: hot-reload on the mounted source. A production deploy drops
# both `command` and `volumes` and runs the image's baked-in CMD.
command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
volumes:
- ./backend/app:/app/app:ro
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8000/api/instance')"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
agent:
build: ./agent
# agent/.env is written for host runs (127.0.0.1); the .docker overlay,
# loaded second, re-points the DB and Playwright MCP at container names.
env_file:
- agent/.env
- agent/.env.docker
restart: unless-stopped
# The hunter runs as a daemon: it LISTENs for work and claims it as it
# appears, so a UI-triggered hunt or "check prices" starts in seconds
# rather than on the next tick. SIGTERM unwinds the pools and hands every
# in-flight job back to the queue; the grace period is how long that gets
# before the kill.
#
# The Playwright MCP this talks to (PLAYWRIGHT_MCP_URL in agent/.env.docker)
# must run with --isolated: the daemon opens one browser context per job,
# and a server on a persistent profile refuses the second one.
command: python main.py --serve
stop_grace_period: 30s
frontend:
build: ./frontend
ports:
- "8081:80" # 8080 is taken by VS Code on this machine
depends_on:
- backend
# --- vision profile (opt-in): docker compose --profile vision up --build ------
# The visual-authenticity sidecar and its object store. Optional by design:
# with VISION_SIDECAR_URL unset in backend/agent the feature is off
# and plain `docker compose up` is unchanged. LAN-INTERNAL, UNAUTHENTICATED —
# publish these ports to trusted interfaces only.
minio:
image: minio/minio
profiles: ["vision"]
command: server /data --console-address ":9001"
environment:
# must match S3_ACCESS_KEY / S3_SECRET_KEY in vision/.env
MINIO_ROOT_USER: ${MINIO_ROOT_USER:-snagr-minio}
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-snagr-minio-secret}
volumes:
- minio-data:/data # image bytes persist here
# ports:
# - "9001:9001" # minio web console — enable for debugging only
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 30s
timeout: 5s
retries: 3
vision:
build: ./vision
profiles: ["vision"]
env_file: vision/.env
environment:
S3_ENDPOINT: http://minio:9000 # in-network address overrides vision/.env
ports:
- "8100:8100" # host-run agent / backend dev servers reach it here
depends_on:
- minio
volumes:
- vision-hf-cache:/home/vision/.cache/huggingface # weights survive restarts
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8100/health')"]
interval: 30s
timeout: 5s
retries: 3
start_period: 60s # first start may be downloading weights
volumes:
minio-data:
vision-hf-cache: