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.

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​