Docker
Run Sieve with Docker Compose or build your own image.
Docker Compose
sieve init --docker docker compose up -d
Creates sieve.toml, .env, abis/, and docker-compose.yml. Starts PostgreSQL and Sieve with GraphQL API on port 4000. Credentials come from .env. Edit sieve.toml for your contracts, or use the default USDC Transfer config.
The generated compose file exposes the discv5 UDP port (30304) that OP Mainnet, Unichain, and World Chain need for peer discovery.
Manual build
docker build -t sieve . docker run \ -v ./sieve.toml:/app/sieve.toml:ro \ -v ./abis:/app/abis:ro \ -p 4000:4000 -p 30303:30303 -p 30303:30303/udp \ -p 30304:30304/udp \ sieve --database-url postgres://... --api-port 4000
Config and ABIs are mounted as volumes, not baked into the image. One image works for dev, staging, and production.
To skip the build, use the prebuilt release image ghcr.io/slvdev/sieve:latest, the same one the generated docker-compose.yml uses.
Networking
Port 30303 (TCP + UDP) carries RLPx and discovery and must be reachable from the internet. If you're behind NAT or a firewall, make sure it is forwarded.
OP Mainnet, Unichain, and World Chain also use UDP 30304 for discv5. Base runs its basev0 discovery on 30303/UDP and needs nothing extra. Expose the ports your chain needs.
Use sieve peers to test connectivity before running the full indexer. It reports peer count and chain head every 5 seconds, useful for diagnosing Docker/NAT issues.
Base archive imports
[archive] paths resolve next to the config, so inside the container they land under /app. Mount the manifest, and mount the staging directory as a writable volume so the retained headers survive container restarts.
-v ./base-manifest.json:/app/base-manifest.json:ro \ -v ./archive-stage:/app/archive-stage
Stopping
docker stop sends SIGTERM. Sieve treats it like Ctrl+C: it drains in-flight work and saves progress before exiting. Docker kills the container after 10 seconds by default, so raise the timeout if the drain needs longer, with docker stop -t or stop_grace_period in your compose file. See Sync & Follow.
Exposing the API
The GraphQL server has open CORS and no built-in auth. Put it behind a reverse proxy with TLS, access control, and rate limiting before exposing it to the internet.
Multiple instances
One container per instance is the simplest way to run several chains on one host, since each gets its own network namespace. Each instance still needs its own database and API port, and a worker cap so they don't oversubscribe the cores. See Multiple Instances.