Skip to main content

Docker Compose

The repository ships a production-ready docker-compose.yml at the repo root. This page is the annotated reference. The API service is built from the Dockerfile in the same repo; FlareSolverr and Tor come from public images.

The compose file

services:
pry:
build: .
container_name: pry
restart: unless-stopped
ports:
- "127.0.0.1:8005:8002"
volumes:
- pry-data:/app/pry-data
- pry-sessions:/app/sessions
env_file: .env
environment:
- PYTHONUNBUFFERED=1
- PRY_TIMEOUT=60
- PRY_API_KEY=${PRY_API_KEY:-}
- PRY_DATA_DIR=/app/pry-data
- PRY_FLARESOLVERR_URL=http://flaresolverr:8191/v1
- TOR_ENABLED=0
- TOR_SOCKS5_HOST=tor
- TOR_SOCKS5_PORT=9050
- PROXY_URL=
- PROXY_TYPE=http
- IP_ROTATION=off
- MAX_RETRIES=3
- MIN_QUALITY=20
- RATE_LIMIT_RPM=120
healthcheck:
test: ["CMD", "python3", "-c", "import urllib.request, sys; sys.exit(0 if urllib.request.urlopen('http://localhost:8002/health', timeout=10).status == 200 else 1)"]
interval: 15s
timeout: 5s
retries: 3
start_period: 30s
deploy:
resources:
limits:
memory: 2G
cpus: "2"
depends_on:
flaresolverr:
condition: service_healthy

flaresolverr:
image: ghcr.io/flaresolverr/flaresolverr:latest
container_name: pry-flaresolverr
restart: unless-stopped
ports:
- "127.0.0.1:8192:8191"
environment:
- LOG_LEVEL=info
- CAPTCHA_SOLVER=none
healthcheck:
test: ["CMD", "curl", "-sf", "http://localhost:8191/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
deploy:
resources:
limits:
memory: 512M
cpus: "1"

tor:
image: dperson/torproxy:latest
container_name: pry-tor
restart: unless-stopped
ports:
- "127.0.0.1:9050:9050"
- "127.0.0.1:9051:9051"
deploy:
resources:
limits:
memory: 128M
cpus: "0.5"
profiles:
- tor

volumes:
pry-data:
pry-sessions:
pry-redis:
pry-postgres:

Services

ServicePurposeNotes
pryThe FastAPI applicationBuilt from the repo Dockerfile; runs uvicorn on container port 8002
flaresolverrCloudflare/WAF challenge bypassHeadless-Chrome sidecar; required for Cloudflare bypass
torAnonymous routing (SOCKS5)Only starts with docker compose --profile tor up

Ports

ServiceHostContainerBind
Pry API80058002127.0.0.1 (loopback only)
FlareSolverr81928191127.0.0.1
Tor SOCKS90509050127.0.0.1 (tor profile)
Tor control90519051127.0.0.1 (tor profile)
important

All host ports bind to 127.0.0.1 only. Put a reverse proxy (nginx) in front for external access — see Production Deployment.

Environment variables

env_file: .env loads a .env file next to the compose file. The inline environment: block overrides/pins defaults that matter for containers.

Key vars wired in the compose file:

VariableDefaultMeaning
PRY_API_KEY(empty)Fail-closed API key; empty = loopback-only
PRY_DATA_DIR/app/pry-dataRoot for on-disk data (quality, monitors, sessions)
PRY_FLARESOLVERR_URLhttp://flaresolverr:8191/v1Sidecar address inside the compose network
PRY_TIMEOUT60Default request timeout (seconds)
RATE_LIMIT_RPM120Requests per minute per IP
MAX_RETRIES3Retry count for failed scrapes
MIN_QUALITY20Minimum quality score to accept a scrape
TOR_ENABLED0Enable Tor routing (requires tor profile)
TOR_SOCKS5_HOST / TOR_SOCKS5_PORTtor / 9050Tor SOCKS5 endpoint

The full set of supported variables (secrets backend, proxy pool, stealth, Redis, Postgres, x402, MCP) is documented on the Configuration page.

Persistence

Two named volumes keep data across container restarts:

VolumeMountContents
pry-data/app/pry-dataQuality history, monitors, reviews, intel, GDPR records, pipelines, reports, training data, agency data
pry-sessions/app/sessionsPersistent browser sessions and saved session state

pry-redis and pry-postgres are declared so you can attach optional Redis / Postgres services without touching the volume list.

:::tip Default data layout

On bare metal (no Docker), data lives under ~/.pry/ — see Architecture for the full directory map.

:::

Health checks

  • pry probes GET /health inside the container every 15s (30s start period).
  • flaresolverr probes GET /health on its internal port every 30s.
  • pry starts only after flaresolverr reports healthy (depends_on.condition).

Resource limits

  • pry: 2 GB memory, 2 CPUs
  • flaresolverr: 512 MB memory, 1 CPU
  • tor: 128 MB memory, 0.5 CPU

Adjust deploy.resources.limits to match your workload. Playwright-based scraping is memory-hungry; budget accordingly.

Running with Tor

docker compose --profile tor up -d

The tor service is opt-in. Enable it with TOR_ENABLED=1 in .env (or PRY_TOR_ENABLED=true). Note: Tor tier support currently requires the aiohttp-socks dependency — see Troubleshooting if the Tor tier reports a missing-module error.

Next steps