Files
rengine/docker-compose.yml
T
Yogesh OjhaandClaude Opus 5 344a1cda99 fix(compose): the api reloads on every package it mounts
The reloader watched eight of the ten packages compose mounts into the
api, so a save in interest/ or connectors/ served stale code until the
container was restarted. The entrypoint builds --reload-dir from one
list, and a touch of interest/providers/rules/provider.py now reloads.

worker-default, worker-beat and flower repeated the same fourteen
mounts; the list is declared once and the three share it, so beat and
flower cannot drift from the worker. The rendered config is unchanged
apart from the anchor itself.

celery_beat_data was declared and mounted nowhere — beat keeps its
schedule in /tmp deliberately, after a stale shelve bit once.

.github is 33 MB of README screenshots and reached every build
context; the api context is 45 MB down to 11 MB.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DafWxfoWZXVDgr9KroJBDZ
2026-09-16 11:33:06 +05:30

274 lines
7.4 KiB
YAML

# every image that runs worker code mounts the same tree, so beat, the stream
# and flower cannot drift from the worker
x-worker-volumes: &worker-volumes
- ./worker/app:/app/app
- ./shared:/app/shared
- ./tools:/app/tools
- ./stages:/app/stages
- ./reports:/app/reports
- ./interest:/app/interest
- ./toolbox:/app/toolbox
- ./scan_media:/app/scan_media
- vuln_templates:/app/vuln-templates
- wordlists:/app/wordlists
- reports_out:/app/reports-out
- exports_out:/app/exports-out
- report_fonts:/app/report-fonts
# the editable installs the image built; a host mount must not shadow them
- /app/shared/build
- /app/shared/rengine_shared.egg-info
- /app/tools/build
- /app/tools/rengine_tools.egg-info
services:
db:
image: postgres:16-alpine
shm_size: ${POSTGRES_SHM_SIZE:-1gb}
env_file:
- .env
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "${BIND_ADDR:-127.0.0.1}:5432:5432"
command: >
postgres
-c shared_buffers=${POSTGRES_SHARED_BUFFERS:-2GB}
-c effective_cache_size=${POSTGRES_EFFECTIVE_CACHE_SIZE:-6GB}
-c work_mem=${POSTGRES_WORK_MEM:-32MB}
-c maintenance_work_mem=${POSTGRES_MAINTENANCE_WORK_MEM:-512MB}
-c random_page_cost=1.1
-c effective_io_concurrency=200
-c max_parallel_workers_per_gather=4
-c jit=off
-c max_connections=${POSTGRES_MAX_CONNECTIONS:-150}
-c shared_preload_libraries=pg_stat_statements
-c pg_stat_statements.max=5000
-c pg_stat_statements.track=top
-c track_io_timing=on
-c log_min_duration_statement=${POSTGRES_LOG_MIN_DURATION:-2000}
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER:-rengine}"]
interval: 5s
timeout: 5s
retries: 5
redis:
image: redis:8-alpine
ports:
- "${BIND_ADDR:-127.0.0.1}:6379:6379"
volumes:
- redis_data:/data
environment:
REDIS_PASSWORD: ${REDIS_PASSWORD:-}
healthcheck:
test:
[
"CMD-SHELL",
"redis-cli $${REDIS_PASSWORD:+-a \"$$REDIS_PASSWORD\"} --no-auth-warning ping | grep -q PONG",
]
interval: 5s
timeout: 5s
retries: 5
command: >
redis-server
--appendonly yes
--maxmemory ${REDIS_MAXMEMORY:-1gb}
--maxmemory-policy noeviction
${REDIS_PASSWORD:+--requirepass} ${REDIS_PASSWORD:-}
api:
image: rengine-api:latest
build:
context: .
dockerfile: api/Dockerfile
target: development
volumes:
- ./api/app:/app/app
- ./shared:/app/shared
- ./tools:/app/tools
- ./stages:/app/stages
- ./reports:/app/reports
- ./interest:/app/interest
- ./mcp:/app/mcp
- ./channels:/app/channels
- ./connectors:/app/connectors
- ./toolbox:/app/toolbox
- ./binaries:/app/binaries:ro
- ./alembic:/app/alembic
- ./alembic.ini:/app/alembic.ini
- ./tests:/app/tests
- ./pyproject.toml:/app/pyproject.toml
# read-only, so the tests can check a frontend mirror has not drifted
- ./frontend/src/lib/config:/app/frontend-config:ro
- ./scan_media:/app/scan_media
- vuln_templates:/app/vuln-templates
- wordlists:/app/wordlists
- reports_out:/app/reports-out
- exports_out:/app/exports-out
- report_fonts:/app/report-fonts
- /app/shared/build
- /app/shared/rengine_shared.egg-info
- /app/tools/build
- /app/tools/rengine_tools.egg-info
ports:
- "${APP_BIND_ADDR:-0.0.0.0}:8000:8000"
env_file:
- .env
environment:
- WATCHFILES_FORCE_POLLING=true
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
# default workers for handling regular tasks like imports, whois etc
worker-default:
init: true
image: rengine-worker:latest
build:
context: .
dockerfile: worker/Dockerfile
target: development
volumes: *worker-volumes
env_file:
- .env
# the widest level holds 5 stages
command: >
uv run celery -A app.celery worker
--loglevel=DEBUG
--concurrency=${CELERY_SCAN_CONCURRENCY:-12}
--queues=critical,default,scans
--hostname=worker-default@%h
--max-tasks-per-child=100
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
healthcheck:
test: ["CMD-SHELL", "/app/.venv/bin/celery -A app.celery inspect ping -d worker-default@$$HOSTNAME || exit 1"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
# beat scheduler: emits the schedule tick that fires due scan schedules
worker-beat:
init: true
# built by worker-default
image: rengine-worker:latest
volumes: *worker-volumes
env_file:
- .env
command: >
uv run celery -A app.celery beat
--loglevel=INFO
--schedule=/tmp/celerybeat-schedule
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
# certificate transparency stream for watched programs
ct-stream:
init: true
# built by worker-default
image: rengine-worker:latest
volumes:
- ./worker/app:/app/app
- ./shared:/app/shared
- ./tools:/app/tools
- ./stages:/app/stages
- ./reports:/app/reports
- ./interest:/app/interest
- ./toolbox:/app/toolbox
- ct_state:/app/ct-state
- /app/shared/build
- /app/shared/rengine_shared.egg-info
- /app/tools/build
- /app/tools/rengine_tools.egg-info
env_file:
- .env
command: uv run python -m app.ct_stream
restart: unless-stopped
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
# remote control: long-polls every chat channel that is switched on
channels:
init: true
# built by api
image: rengine-api:latest
volumes:
- ./api/app:/app/app
- ./shared:/app/shared
- ./tools:/app/tools
- ./stages:/app/stages
- ./reports:/app/reports
- ./interest:/app/interest
- ./mcp:/app/mcp
- ./channels:/app/channels
- ./connectors:/app/connectors
- ./toolbox:/app/toolbox
- /app/shared/build
- /app/shared/rengine_shared.egg-info
- /app/tools/build
- /app/tools/rengine_tools.egg-info
env_file:
- .env
command: uv run python -m channels
restart: unless-stopped
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
api:
condition: service_started
flower:
# built by worker-default
image: rengine-worker:latest
volumes: *worker-volumes
profiles: ["debug"]
ports:
- "${BIND_ADDR:-127.0.0.1}:5555:5555"
env_file:
- .env
command: >
uv run celery -A app.celery flower
--port=5555
--basic-auth=${FLOWER_USER:-admin}:${FLOWER_PASSWORD:-admin}
depends_on:
redis:
condition: service_healthy
frontend:
build:
context: .
dockerfile: frontend/Dockerfile.dev
volumes:
- ./frontend/src:/app/src
- ./frontend/vite.config.ts:/app/vite.config.ts
ports:
- "${APP_BIND_ADDR:-0.0.0.0}:5173:5173"
environment:
- NODE_ENV=development
depends_on:
- api
volumes:
ct_state:
postgres_data:
redis_data:
vuln_templates:
wordlists:
exports_out:
reports_out:
report_fonts: