Migrate from Docker Compose to Bahriya

A docker-compose.yml describes several services that run together on one host: your app, maybe a worker, a database, a cache, and the wiring between them. Bahriya runs the same services, but each one is deployed and scaled individually across the regions you choose — there is no single compose up that brings the whole stack up at once. This guide maps a compose file onto Bahriya resources and walks the move.

Updated 3 Aug 20264 min read

A docker-compose.yml describes several services that run together on one host: your app, maybe a worker, a database, a cache, and the wiring between them. Bahriya runs the same services, but each one is deployed and scaled individually across the regions you choose — there is no single compose up that brings the whole stack up at once. This guide maps a compose file onto Bahriya resources and walks the move.

What maps to what

Docker ComposeBahriya
A service that serves trafficAn HTTP container
A service that runs in the backgroundA worker container
A scheduled taskA cron job
build: / image:The image you build and push to a registry
ports:The port you declare with --port
environment: (non-sensitive)Environment variables
environment: (sensitive) / secrets:Secrets (encrypted, injected as env vars)
depends_on: a database serviceAn external database via a connection secret
depends_on: a cache serviceBahriya Memcached, or an external cache via a secret
volumes:Ephemeral or persistent storage
Compose network / service namesExplicit connection strings held as secrets

The key difference

Compose treats the file as one unit — every service starts together and they reach each other by service name on a shared network. On Bahriya you deploy each service as its own container. That means two things:

  1. There is no automatic service discovery by name. Where one service talked to another as db:5432 or cache:11211, you supply an explicit address — a database's network address stored as a secret, or a Bahriya Memcached endpoint.
  2. Each container has its own regions, resources, and scaling. Deploy them one at a time; the platform-managed add-ons (database, cache) are not containers you run yourself.

1. Take stock of the compose file

Go through each service and decide its Bahriya shape:

  • Your app service — an HTTP container if it exposes a port, a worker if it does not.
  • A queue consumer or background job — a worker container.
  • A cron-style service — a cron job.
  • A database service (postgres, mysql, mongo) — not a container you deploy. Provision a database elsewhere and connect over the network.
  • A cache service (memcached, redis) — Bahriya Memcached for Memcached, or an external cache reached via a secret.

2. Build and push each app image

For every service you will run as a container, build its image and push it to a registry:

docker build -t ghcr.io/myorg/api:v1.0.0 .
docker push ghcr.io/myorg/api:v1.0.0

If your compose service used build:, that build context and Dockerfile carry straight over.

3. Ports

A compose ports: mapping like "8080:8080" tells you the port your app listens on. Declare that container port with --port (default 8080) and bind your server to 0.0.0.0. Bahriya provides the public HTTPS hostname — you do not map host ports yourself.

4. Environment and secrets

Split each service's environment: block:

  • Non-sensitive entries become plain environment variables.
  • Sensitive entries, and anything under compose secrets:, become secrets — created once, attached to the project, and wired to the variable name your app reads.

Replace inter-service references. Where the app read DATABASE_URL=postgres://db:5432/app, point it at the real address of your provisioned database, stored as a secret. Where it read a cache host of cache, use your Bahriya Memcached endpoint.

5. Volumes

A compose volumes: entry becomes storage on the container. Use ephemeral storage for scratch space that need not survive a restart, or persistent storage for data that must. Note that a database's data volume belongs to your external database, not to a Bahriya container.

6. Deploy each service

Deploy the services one at a time. From the Console follow Deploy Your First Container, or with Reis:

# The web service
reis container:create \
  --type http \
  --name "Web" \
  --handle web \
  --image ghcr.io/myorg/api:v1.0.0 \
  --registry ghcr \
  --port 8080 \
  --healthcheck /healthz \
  --regions falkenstein-1 \
  --env APP_ENV=production \
  --secrets DATABASE_URL=database-url
 
# A background worker from the same or a different image
reis container:create \
  --type worker \
  --name "Worker" \
  --handle worker \
  --image ghcr.io/myorg/worker:v1.0.0 \
  --registry ghcr \
  --regions falkenstein-1 \
  --secrets DATABASE_URL=database-url

Put related services in the same project so they share secrets and configuration.

7. Point your domain and cut over

Your HTTP container is reachable at https://web.<region>.x.on.bahriya.app with automatic TLS. Test the whole stack against the default hostnames, then add your production domain to the public service, verify it, and move DNS across — see Custom Domain Setup.