Docker deployment
Docker fits private networks / VPC, self-managed hosts or Kubernetes, and Postgres/MySQL with your existing DBA practices. The default recommendation remains Cloudflare Workers (individuals and light traffic can usually stay in the free tier).
Local quickstart
Section titled “Local quickstart”git clone https://github.com/OctaFuse/octafuse-gateway.gitcd octafuse-gatewaydocker compose -f docker/compose/quickstart.yml up --buildThis compose starts Postgres + migrate + Proxy + Admin:
- Proxy:
http://localhost:8787 - Admin:
http://localhost:8789, default loginadmin / changeme - Default admin Bearer key:
sk-dev-admin-key
If local ports conflict, set POSTGRES_HOST_PORT, GATEWAY_PROXY_HOST_PORT, or GATEWAY_ADMIN_HOST_PORT. For the Cloudflare default path, see Quick start.
Production self-host
Section titled “Production self-host”Production usually follows one of two paths: build images locally, or run GHCR / private registry images. In both cases, prefer migrate first, then start Proxy/Admin; alternatively enable AUTO_MIGRATE=1 on only one service.
Option A: Local images + bundled database
Section titled “Option A: Local images + bundled database”Postgres:
docker compose -f docker/compose/node-pg.yml up -d postgresdocker compose -f docker/compose/node-pg.yml --profile migrate run --rm migratedocker compose -f docker/compose/node-pg.yml up -d gateway-proxy gateway-adminMySQL 8:
docker compose -f docker/compose/node-mysql.yml up -d mysqldocker compose -f docker/compose/node-mysql.yml --profile migrate run --rm migratedocker compose -f docker/compose/node-mysql.yml up -d gateway-proxy gateway-adminFor MySQL, set DATABASE_DRIVER=mysql and use a mysql://... DATABASE_URL.
Option B: Prebuilt images + external Postgres
Section titled “Option B: Prebuilt images + external Postgres”docker/examples/ contains the production-style templates: Proxy only, Admin only, or Proxy + Admin on one host. Keep env files out of Git; docker/deploy/ is the intended local location.
cp docker/examples/env.compose.external.example docker/deploy/.env.local# Edit docker/deploy/.env.local: image tags, DATABASE_URL, ADMIN_PASSWORD, etc.docker compose --env-file docker/deploy/.env.local -f docker/examples/gateway.compose.yml --profile migrate run --rm migratedocker compose --env-file docker/deploy/.env.local -f docker/examples/gateway.compose.yml up -dImage names depend on your registry and repo, commonly:
ghcr.io/<owner>/<repo>-proxy:<tag>ghcr.io/<owner>/<repo>-admin:<tag>ghcr.io/<owner>/<repo>-migrate:<tag>
Option C: Build individual images
Section titled “Option C: Build individual images”From the repo root:
docker build -f Dockerfile.proxy -t octafuse-proxy:local .docker build -f Dockerfile.admin -t octafuse-admin:local .docker build -f Dockerfile.migrate -t octafuse-migrate:local .Dockerfile.migrate is a one-shot migration job; Dockerfile.proxy and Dockerfile.admin are long-running application images.
Key environment variables
Section titled “Key environment variables”DATABASE_URL: Proxy, Admin, and migrate must point at the same database.DATABASE_DRIVER: optional for Postgres; required asmysqlfor MySQL.ADMIN_USERNAME/ADMIN_PASSWORD: Admin login, needed only by the Admin container.AUTO_MIGRATE: optional. When set to1, an app container runs idempotent migrations before startup; production can instead use a dedicated migrate job.GATEWAY_PROXY_PORT/GATEWAY_ADMIN_PORT: host port mappings only; containers still listen on8787/8789.
For Postgres, keep the connection/session timezone at UTC; when using DATABASE_URL, you can add options=-c timezone=UTC. For MySQL, keep the instance or session timezone at UTC as well to make request-log time windows easier to reason about.
Smoke test
Section titled “Smoke test”curl -fsS http://127.0.0.1:8787/healthcurl -fsS http://127.0.0.1:8789/api/admin/config \ -H 'Authorization: Bearer sk-dev-admin-key'vs Cloudflare
Section titled “vs Cloudflare”- Need data residency + private networking → Docker/self-host.
- Need edge + managed D1 → Cloudflare Workers.