The quickest way to run iron-defer with Postgres:
docker compose -f docker/docker-compose.yml upThis starts Postgres and iron-defer with health-check dependencies. See docker/docker-compose.yml.
For development (Postgres only):
docker compose -f docker/docker-compose.dev.yml up -dThe Dockerfile uses a multi-stage build:
- Builder stage (rust:1.94-slim) — compiles the release binary with
SQLX_OFFLINE=true - Runtime stage (distroless/cc-debian12) — minimal image with just the binary
Build manually:
docker build -f docker/Dockerfile -t iron-defer .
docker run -e DATABASE_URL=postgres://user:pass@host:5432/db -p 8080:8080 iron-deferiron-defer uses the IRON_DEFER__ prefix with double underscores for nested fields:
| Variable | Description |
|---|---|
DATABASE_URL |
PostgreSQL connection string |
PORT |
HTTP listen port |
IRON_DEFER__DATABASE__URL |
Alternative to DATABASE_URL |
IRON_DEFER__DATABASE__MAX_CONNECTIONS |
Connection pool size |
IRON_DEFER__SERVER__PORT |
Alternative to PORT |
IRON_DEFER__WORKER__CONCURRENCY |
Max in-flight tasks |
IRON_DEFER__OBSERVABILITY__OTLP_ENDPOINT |
OTLP collector endpoint |
See Configuration Guide for the full reference.
On SIGTERM/SIGINT, iron-defer:
- Cancels the
CancellationToken— stops accepting new work - Drains in-flight tasks up to
shutdown_timeout(default: 30s) - If drain times out, the process exits; the sweeper on next startup recovers any orphaned tasks
| Probe | Endpoint | Behavior |
|---|---|---|
| Liveness | GET /health |
Always 200 |
| Readiness | GET /health/ready |
200 when DB is reachable, 503 otherwise |
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5Run the smoke test after deploying:
./docker/smoke-test.sh http://localhost:8080This validates health probes, task creation, task retrieval, and metrics endpoint. See docker/smoke-test.sh.