Deploy with Docker Compose
A site with the Docker Compose runtime is a Compose project that Falak deploys, routes, observes and rolls back. Use it for apps made of several containers (an app plus Redis, a worker, a search engine) or anything published as a compose.yaml. Templates are Compose sites too.
Prerequisites
Section titled “Prerequisites”- A server of type app, web or worker with Docker installed (tick Install Docker Engine when you create the server).
- For a Compose file in your repository: a builder that can do Docker builds (a
builderserver), even if no service usesbuild:.
Choose the source
Section titled “Choose the source”| Source | API value | Compose file | build: allowed |
|---|---|---|---|
| Repository | repo |
compose_files in the repository (-f order, plus compose_profiles); default compose.yaml, then docker-compose.yml |
Yes (built by the builder, pushed to Falak’s registry, referenced by digest) |
| Inline | inline |
Pasted into Falak, versioned (history and restore, newest 50 kept) | No |
Deploy
Section titled “Deploy”- + Create → Git repository, then choose Docker Compose app as the app type and enter the compose file (or paste a Compose file, or deploy a template).
- Decide where each service runs: in the stack, public (with its container port, a domain and an optional health check path), as a Falak database, or as its own Falak site.
- Pick servers. Every server runs the whole project (replicated).
- Create. The first deploy starts.
The repository flow (override files, profiles, the services table, variables and Falak’s adjustments) is described in Compose apps from git.
Through the API, create the site with runtime: "compose":
{ "name": "Wiki", "runtime": "compose", "server_ids": ["01k…"], "compose_source": "inline", "compose_content": "services:\n app:\n image: ghcr.io/requarks/wiki:2.5\n expose: [\"3000\"]\n", "public_services": [{"service": "app", "port": 3000, "domain": {"type": "generated"}}], "variables": {"DB_PASS": "change-me"}}How Falak renders your Compose file
Section titled “How Falak renders your Compose file”For every release Falak renders the file the servers receive:
- Ports: host
ports:mappings are removed from all services. Each public service gets127.0.0.1:<allocated host port>:<container port>, and Caddy routes its domain there with HTTPS. - Images: built services are pinned to the built image digest; pulled images are pinned to the digest the server resolved on the first deploy, so a rollback is exact.
- Variables: interpolation stays Compose-native (
${VAR}). Your site variables (with${{ service.KEY }}references resolved) are written to the project’s.envnext tocompose.yaml, plusFALAK_SITE_ID,FALAK_SERVER_ID,FALAK_DEPLOYMENT_IDandFALAK_RELEASE_ID. - Restart policy: in repository and inline stacks, every service without one gets
restart: unless-stopped, so the stack comes back after a server reboot. Inline stacks (including ones created through the API) get it at every deploy since v0.7.1; before, they stayedExitedafter a reboot. - Repository stacks also get Falak adjustments:
container_nameremoved, missing bind sources as named volumes, repository files shipped with the release. - Labels: every service gets
falak.site,falak.releaseandfalak.servicefor log and metric attribution. - Project name: the site slug. Because it never changes, named volumes persist across releases.
The deploy flow
Section titled “The deploy flow”FETCH write releases/<ID>/compose.yaml + .env, docker compose pullLEADER docker compose run --rm <service> <command> for each falak.deploy.leader_command labelACTIVATE docker compose up -d --remove-orphans --wait --wait-timeout 300HEALTH HTTP check of every public service through the edgeROLLBACK on failure: up --wait with the previous release's filesHealth checks: each public service is requested through its own domains at its health check path; without one, the primary public service uses the site’s health path and expected status, and other public services must answer / with a status below 500. Give services Docker healthchecks so --wait means “ready”. Raise the wait with FALAK_COMPOSE_WAIT_TIMEOUT (seconds) for slow starters.
Run a command once, on the leader
Section titled “Run a command once, on the leader”Add the label falak.deploy.leader_command to a service to run a command once per deployment, on the leader, before activation (migrations, for example):
services: app: image: ghcr.io/acme/app:2.3.0 expose: ["8080"] labels: falak.deploy.leader_command: "php artisan migrate --force"Falak runs docker compose run --rm app php artisan migrate --force. Arguments are split like a shell would, and quotes must be balanced.
Domains for public services
Section titled “Domains for public services”| Service | Generated domain | Test domain |
|---|---|---|
| First public service (primary) | <service>-<slug>.<leader-ip-with-dashes>.sslip.io |
<slug>.<FALAK_TEST_DOMAIN> |
| Other public services | <service>-<slug>.<ip>.sslip.io |
<service>-<slug>.<FALAK_TEST_DOMAIN> |
Every public service has domains of its own: add several per service, with Cloudflare records, cache modes and routing rules, in Settings → Networking (service picker). See Edge for every public service.
Security policy
Section titled “Security policy”Unless an admin enables Allow privileged compose (organization setting under Settings → Compose, permission sites.compose.policy), Falak refuses a Compose file — inline files when you save them, and every source (repository, inline, template) when a release is rendered — if a service uses:
privileged: truenetwork_mode: hostorpid: hostcap_addbeyond Docker’s default set (AUDIT_WRITE,CHOWN,DAC_OVERRIDE,FOWNER,FSETID,KILL,MKNOD,NET_BIND_SERVICE,NET_RAW,SETFCAP,SETGID,SETPCAP,SETUID,SYS_CHROOT)- host bind mounts outside the release directory
devices- a
/var/run/docker.sockmount
Named volumes are always allowed. Compose files are limited to 256 KiB.
In the UI
Section titled “In the UI”- The canvas draws a Compose site as a group: one card per service with its state, image, public URL and volumes, and
depends_onarrows. - The Services tab lists each service’s state and health, image digest, ports, restarts, CPU and memory, with Restart and Logs actions.
- Settings → Compose edits the source (files and profiles for repository stacks), the services table, the public services and their health check paths, shows the Falak adjustments and, for inline files, history and diff.
⋯ → Save as templateturns the site into a custom template.
Container logs reach Loki with service.name=<slug> and the Compose service name; filter by service in the Logs tab. docker stats feeds CPU, memory and network metrics per container.
Limits
Section titled “Limits”- Repository stacks ship the files they mount or read with each release (at most 200 files / 2 MB). Inline files and templates ship only
compose.yamland.env. includeandextendswork for repository stacks (files from the repository only); inline files and templates can’t use them.- A failed first deployment has nothing to roll back to; the containers stay as
docker compose upleft them (so you can read their logs). - Stateful apps on several servers each get their own volumes; Falak warns when a stateful template is deployed to more than one server.
- Processes from the Processes tab (workers, cron) are not run for Compose sites; add them as Compose services.