Deploy / Docker and EC2

Docker and EC2

No platform, no config schema — a container and something that restarts it.

services:
  indexer:
    build: .
    restart: unless-stopped
    env_file: .env
    ports: ["8080:8080"]
    healthcheck:
      test: ["CMD", "wget", "-qO-", "http://localhost:8080/health"]
      interval: 30s
      timeout: 5s
      retries: 3
    depends_on: [postgres]

  postgres:
    image: postgres:17-alpine
    restart: unless-stopped
    environment:
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: sales
    volumes: ["./data/postgres:/var/lib/postgresql/data"]
docker compose up -d
docker compose logs -f indexer

restart: unless-stopped covers crashes and host reboots. Docker's own healthcheck reports status but won't restart a wedged container on its own — pair it with a supervisor or an external probe if you want that.

Stop grace period

docker compose stop sends SIGTERM and kills after 10s by default. A batch mid-commit against a slow database can exceed that — raise it with stop_grace_period: 60s on the service.

Skipping containers:

[Unit]
After=network-online.target

[Service]
ExecStart=/usr/local/bin/bun run /srv/sales-index/indexer.ts
EnvironmentFile=/srv/sales-index/.env
Restart=always
RestartSec=5
KillSignal=SIGTERM
TimeoutStopSec=60

[Install]
WantedBy=multi-user.target

KillSignal=SIGTERM and a generous TimeoutStopSec are what let the shutdown handler finish its transaction before systemd escalates to SIGKILL.

Local Postgres in the same compose file keeps latency near zero, which matters most during a genesis backfill. Point DATABASE_URL at a managed instance instead when you'd rather not own backups.