Compose stacks let you run multiple containers together on a single App VM. One service is exposed over the public URL; the rest are internal, reachable from each other by service name.
Before you start
You need a running App VM with compose enabled (choose Compose stack when creating), or create a new one. All services must reference pre-built images from a registry unless you supply a public git URL (which allows build: services).
1. Choose a source
When you create a compose App VM, pick one of two sources:
Paste a compose file — enter the contents of your docker-compose.yml directly. Every service must have an image: field pointing at a pre-built, publicly reachable or credentialed image. The build: directive is not supported with a pasted file.
Public git URL — enter an https:// URL to a public repository. The platform clones the repo and builds services with build: directives on the VM. Optionally specify a branch, tag, or commit SHA to pin; a subdirectory path if your compose file is not at the repo root; and an alternate compose file path within that directory.
2. Designate the ingress service
One service receives public traffic. Select it in the Ingress service dropdown. When that service declares a single port in your compose file, the Ingress port field is pre-filled with it; otherwise enter the port the service listens on (1–65535). The declared ports are shown beneath the field as a hint.
You can change the ingress service or port after creation: open the App's detail page, edit the fields in the Configuration card, and choose Save & redeploy. If a deploy failed because the ingress port was wrong, the error includes a link straight to those fields.
All other services are reachable internally by their service name. For example, if your compose file has a db service, your web service connects to it as db:5432.
3. Set environment variables
Supply environment variable values on the vars tab or via PUT /api/app-vms/[id]/env. In your compose file, reference them with ${VAR_NAME}. The platform substitutes values at deploy time; services receive the resolved values. Values are treated literally — a $ in a value (for example a generated password) is preserved, not re-interpreted.
4. Use named volumes
Declare named volumes in your compose file. They persist for the life of the App VM and are deleted when you destroy it. Do not bind-mount host paths — the platform rejects them. See Unsupported features below.
5. Registry credentials
A single account-level registry credential applies to all images in the stack. Select it from the Registry credential dropdown when creating or editing the App. Using images from two different private registries in the same stack is not supported yet — keep all private images on a single registry; public images can be mixed in freely.
6. Deploy
Choose Deploy to start the stack. The App moves to deploying. When all services are healthy, traffic routes to the ingress service and the App returns to running.
To redeploy without changing the source — for example to pull updated images — use Redeploy on the App's detail page (for pasted stacks) or deploy again with a new git ref (for git-backed stacks).
Unsupported features
The following configuration in your compose file causes the App creation or deploy to be rejected. The error message names the field. For any of these, a Plain VM gives you full host control.
| Field | Reason |
|---|---|
privileged: true | requires host root — not supported on App VMs |
cap_add | added Linux capabilities — not supported on App VMs |
devices | host device access — not supported on App VMs |
network_mode: host or network_mode: container:… | host or shared network namespace — not supported on App VMs |
pid: host, ipc: host, uts: host, userns_mode: host | host namespace sharing — not supported on App VMs |
security_opt: …:unconfined | disabling security profiles — not supported on App VMs |
Absolute host bind mounts in volumes | mounts a host path into the container — use a named volume instead |
build: with a pasted compose file | builds require a git source |
extends.file with an absolute path | reads a host file — not supported on App VMs |
Top-level include: | not supported — combine services into one compose file |
Top-level secrets or configs with an absolute file: | reads a host file — not supported on App VMs |
Top-level networks using macvlan or ipvlan driver | host L2 network access — not supported on App VMs |
The platform also ignores ports: declarations — only the designated ingress service is published. container_name, deploy.replicas > 1, and profiles are silently ignored (warnings in the deploy log).
Services cap
A compose stack may contain at most 10 services. Stacks over this limit are rejected at creation time.