Skip to content

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).

Terminal window
git clone https://github.com/OctaFuse/octafuse-gateway.git
cd octafuse-gateway
docker compose -f docker/compose/quickstart.yml up --build

This compose starts Postgres + migrate + Proxy + Admin:

  • Proxy: http://localhost:8787
  • Admin: http://localhost:8789, default login admin / 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 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.

Postgres:

Terminal window
docker compose -f docker/compose/node-pg.yml up -d postgres
docker compose -f docker/compose/node-pg.yml --profile migrate run --rm migrate
docker compose -f docker/compose/node-pg.yml up -d gateway-proxy gateway-admin

MySQL 8:

Terminal window
docker compose -f docker/compose/node-mysql.yml up -d mysql
docker compose -f docker/compose/node-mysql.yml --profile migrate run --rm migrate
docker compose -f docker/compose/node-mysql.yml up -d gateway-proxy gateway-admin

For 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.

Terminal window
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 migrate
docker compose --env-file docker/deploy/.env.local -f docker/examples/gateway.compose.yml up -d

Image 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>

From the repo root:

Terminal window
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.

Before upgrading, read the Upgrade notes in that version’s GitHub Release / Changelog (breaking changes, required migrations). Always prefer migrate first, then roll Proxy / Admin (or enable AUTO_MIGRATE=1 on only one service).

  1. In docker/deploy/.env.local (or your env file), bump the tag on GATEWAY_PROXY_IMAGE / GATEWAY_ADMIN_IMAGE / GATEWAY_MIGRATE_IMAGE (for example v2.1.2; pin semver in production instead of floating on latest).
  2. Pull, migrate, then recreate containers:
Terminal window
docker compose --env-file docker/deploy/.env.local -f docker/examples/gateway.compose.yml pull
docker compose --env-file docker/deploy/.env.local -f docker/examples/gateway.compose.yml --profile migrate run --rm migrate
docker compose --env-file docker/deploy/.env.local -f docker/examples/gateway.compose.yml up -d

If AUTO_MIGRATE=1 is already set, you can up -d after pull (the entrypoint runs idempotent migrations). Still check the Release notes for any maintenance window.

Terminal window
git pull --ff-only
# When new SQL lands, migrate first
docker compose -f docker/compose/node-pg.yml --profile migrate run --rm migrate
# Rebuild and restart apps (use node-mysql.yml for MySQL)
docker compose -f docker/compose/node-pg.yml up -d --build gateway-proxy gateway-admin

For the local quickstart (quickstart.yml): git pull, then docker compose -f docker/compose/quickstart.yml up --build -d.

Terminal window
curl -fsS http://127.0.0.1:8787/health
curl -fsS http://127.0.0.1:8789/api/admin/config \
-H 'Authorization: Bearer <MASTER_KEY>'

Image names, GHCR digests, and Zeabur notes: GitHub · Docker / self-hosted.

  1. DATABASE_URL: Proxy, Admin, and migrate must point at the same database.
  2. DATABASE_DRIVER: optional for Postgres; required as mysql for MySQL.
  3. ADMIN_USERNAME / ADMIN_PASSWORD: Admin login, needed only by the Admin container.
  4. AUTO_MIGRATE: optional. When set to 1, an app container runs idempotent migrations before startup; production can instead use a dedicated migrate job.
  5. GATEWAY_PROXY_PORT / GATEWAY_ADMIN_PORT: host port mappings only; containers still listen on 8787 / 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.

Terminal window
curl -fsS http://127.0.0.1:8787/health
curl -fsS http://127.0.0.1:8789/api/admin/config \
-H 'Authorization: Bearer sk-dev-admin-key'
  • Need data residency + private networking → Docker/self-host.
  • Need edge + managed D1Cloudflare Workers.