Skip to content

Docker Compose

This deployment runs several Gateway replicas behind one TLS edge, sharing one Postgres that you operate. It is the production topology expressed in Compose: the same shape as the ECS and Kubernetes deployments, on a single host.

Overview

By the end you’ll have:

  • Two or more Gateway containers, any of which can be restarted without downtime.
  • A database you control, holding all state.
  • One edge round-robining across the replicas, with no session affinity.

Choose this when you want production behaviour on one host - a staging environment, an on-premises box, or a deployment small enough not to need an orchestrator. If you already run ECS or Kubernetes, use those guides instead.

Before You Begin

You need:

  • Docker with Compose.
  • A Postgres 14+ database the containers can reach. Managed or your own - not the throwaway one from the quickstart.
  • A Britive tenant and pool token. The token decides which gateway pool - and so which settings - the replicas run with.

Deploy

Download the Compose file

Download docker-compose.replicas.yaml - scalable Gateway replicas behind one TLS edge.

Save it as docker-compose.yaml in an empty directory.

Configure the container

Create a .env file beside the Compose file:

.env
TENANT=acme
GATEWAY_POOL_TOKEN=<your-pool-token>
DATABASE_URL=postgresql://gateway:<password>@your-db-host:5432/gateway

Three values, and every replica gets the same three. There is no master secret to generate: the key that protects stored tokens and sessions is minted by the platform for the gateway pool and arrives with the pool’s settings, so replicas are guaranteed to agree on it.

Set the public base URL on the pool

In the Britive tenant portal, open the gateway pool your token belongs to and set Public base URL to the address clients actually use:

https://mcp-gateway.example.internal

If you are putting your own TLS terminator in front of this stack, that is its URL - not the edge inside the Compose file.

Start the replicas

docker compose up -d --scale gateway=3

Compose’s DNS resolves gateway to every replica, and the edge load-balances across all of them - adding or removing replicas needs no edge change.

Confirm they are healthy

docker compose ps
curl -sk https://localhost:8443/healthz

Verify the Replicas Share State

This is the check that proves the deployment is actually shared-state rather than three independent Gateways.

Sign in

Open https://localhost:8443/ and sign in with Britive.

Restart a different replica

docker compose restart gateway

Confirm you are still signed in

Reload the console. You should remain signed in, and the audit history should be unchanged.

If you are signed out, the replicas are not sharing state. Check that every replica carries the same GATEWAY_POOL_TOKEN and the same DATABASE_URL - a token belonging to a different pool means a different encryption key, and a different database means no shared sessions at all.

Rolling Restarts

Because every replica is stateless and shares one database, restarting them one at a time keeps the service up:

docker compose up -d --no-deps --scale gateway=3 gateway

Schema migrations run on startup, so a new image needs no separate migration step. Wait for /healthz to pass before moving on.

Changing Settings

Everything beyond those three environment variables - audit sinks, rate limits, inspection, backend policy - is set on the gateway pool in the Britive tenant portal. There is no file to mount and nothing to redeploy: every replica picks a change up on its next sync, within five minutes by default.

The Gateway’s admin console has a read-only Settings tab showing what each container is actually running, which is where to look when a change does not appear to have landed. See Configuration.

Troubleshoot

SymptomCauseFix
A replica exits at startupThe tenant is unreachable, or the pool token was rejectedFetching settings is fatal at startup by design. The log line names both causes; make doctor tells them apart.
Signed out when reloadingReplicas are not sharing stateSame GATEWAY_POOL_TOKEN and same DATABASE_URL on every replica.
DATABASE_URL is requiredNot set, or unreachable from the containerCheck the value and that the host is routable from Docker.
Only one replica gets trafficScaled after the edge starteddocker compose up -d again; the edge re-resolves the replicas.
OAuth fails at the callbackThe pool’s Public base URL doesn’t match the browser’s addressSet it to the URL people actually open.
A settings change hasn’t taken effectThe next sync hasn’t run, or the last one failedCheck the console’s Settings tab: it flags stale settings and shows the values in force.

Next Steps

Last updated on