Skip to main content
docker-compose.yaml at the repository root is the reference deployment: ten containers, four volumes, one network. This page explains each part and how to change it.
This stack is built for evaluation and development. It bind-mounts source, runs the API with --reload, allows all CORS origins, and ships default passwords. Read Production deployment before exposing it.

Starting

Use make application-up rather than a bare docker compose up. The compose file’s own header says a bare up against a fresh checkout “will fail or come up misconfigured” — three services declare ${SECRET_KEY:?...} and abort without it.

The map

Services

Three services build from one image (apps/api/Dockerfile) and differ only by command. See Workers and orchestrator.
minio-init exiting with code 0 is correct — it creates the bucket and stops. It is not a crash.

Volumes

docker compose down -v deletes all four at once. Back up before running it — see Daily operations.

Network and the mongodb alias

One bridge network, app-network. The ferretdb service publishes the alias mongodb, so in-stack services connect to mongodb:27017 and nothing refers to FerretDB by name. See Data store.

Environment precedence

Each service loads env_file: .env, then applies its own environment: block — and environment: wins. Some values are pinned there deliberately, because the in-network address differs from the host one: Editing these in .env has no effect inside the stack. That is intended.
DEBUG is deliberately not interpolated into environment:. The compose file explains why: host shells often export DEBUG=release, which would override the boolean False from .env. It reaches containers through env_file only — so do not add DEBUG: "${DEBUG}".
Three variables have no default and abort the run if unset: SECRET_KEY on api, arq-worker, and campaign-orchestrator.

Healthchecks and start order

api waits for FerretDB only to start, not to be ready. On a cold first boot it can attempt a query too early and log a connection error. restart: unless-stopped recovers it within seconds.

Overriding ports

Every published port reads from .env:
Container-side ports do not change. See Ports and defaults.

Logs

Every service uses json-file with max-size: 10m and max-file: 3 — about 30 MB per container, so logs cannot fill the disk.

Common operations