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
| Service | Purpose | Notes |
|---|---|---|
pry | The FastAPI application | Built from the repo Dockerfile; runs uvicorn on container port 8002 |
flaresolverr | Cloudflare/WAF challenge bypass | Headless-Chrome sidecar; required for Cloudflare bypass |
tor | Anonymous routing (SOCKS5) | Only starts with docker compose --profile tor up |
Ports
| Service | Host | Container | Bind |
|---|---|---|---|
| Pry API | 8005 | 8002 | 127.0.0.1 (loopback only) |
| FlareSolverr | 8192 | 8191 | 127.0.0.1 |
| Tor SOCKS | 9050 | 9050 | 127.0.0.1 (tor profile) |
| Tor control | 9051 | 9051 | 127.0.0.1 (tor profile) |
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:
| Variable | Default | Meaning |
|---|---|---|
PRY_API_KEY | (empty) | Fail-closed API key; empty = loopback-only |
PRY_DATA_DIR | /app/pry-data | Root for on-disk data (quality, monitors, sessions) |
PRY_FLARESOLVERR_URL | http://flaresolverr:8191/v1 | Sidecar address inside the compose network |
PRY_TIMEOUT | 60 | Default request timeout (seconds) |
RATE_LIMIT_RPM | 120 | Requests per minute per IP |
MAX_RETRIES | 3 | Retry count for failed scrapes |
MIN_QUALITY | 20 | Minimum quality score to accept a scrape |
TOR_ENABLED | 0 | Enable Tor routing (requires tor profile) |
TOR_SOCKS5_HOST / TOR_SOCKS5_PORT | tor / 9050 | Tor 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:
| Volume | Mount | Contents |
|---|---|---|
pry-data | /app/pry-data | Quality history, monitors, reviews, intel, GDPR records, pipelines, reports, training data, agency data |
pry-sessions | /app/sessions | Persistent 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
pryprobesGET /healthinside the container every 15s (30s start period).flaresolverrprobesGET /healthon its internal port every 30s.prystarts only afterflaresolverrreports healthy (depends_on.condition).
Resource limits
pry: 2 GB memory, 2 CPUsflaresolverr: 512 MB memory, 1 CPUtor: 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
- Configuration — every environment variable explained
- Production Deployment — nginx, HTTPS, hardening