Compose Deployments
Docker Compose is the primary deployment method in DaoFlow. Compose files are first-class citizens — DaoFlow preserves both the original file and the rendered runtime spec.
How It Works
- You provide a
compose.yamlfile - DaoFlow uploads or checks out the deployment workspace on the target server
- If the rendered Compose spec contains local
build:services, DaoFlow builds them before start - Runs
docker compose up -dwith the appropriate project name - Waits for Docker Compose container state and Docker health
- If configured, runs an explicit readiness probe from the deployment target host and records the outcome
CLI Deployment
# Preview
daoflow deploy --compose ./compose.yaml --server srv_prod --dry-run
# Deploy
daoflow deploy --compose ./compose.yaml --server srv_prod --yes
Example Compose File
services:
web:
image: node:20-alpine
command: npm start
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DATABASE_URL=${DATABASE_URL}
volumes:
- app-data:/data
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
redis:
image: redis:7-alpine
volumes:
- redis-data:/data
volumes:
app-data:
redis-data:
What DaoFlow Stores
For each Compose deployment, DaoFlow records:
- Original compose.yaml — the file as provided
- Resolved config — with environment variables substituted
- Image tags — exact versions pulled
- Volume mounts — persistent storage configuration
- Environment variables — encrypted values used at deploy time
Multi-Service Support
Compose files with multiple services are deployed as a unit. All services start together, and the deployment is marked as successful only when all services are healthy.
Explicit Readiness Probes
Compose deployments can opt into an explicit readiness probe on the DaoFlow service definition:
{
"readinessProbe": {
"type": "http",
"target": "published-port",
"port": 8080,
"path": "/ready",
"host": "127.0.0.1",
"scheme": "http",
"timeoutSeconds": 60,
"intervalSeconds": 3,
"successStatusCodes": [200, 204]
}
}
Supported readiness probe shapes:
- HTTP against a host-published endpoint
- HTTP against the compose internal network for the targeted compose service
- TCP against a host-published port
- TCP against the compose internal network for the targeted compose service
Execution semantics are deterministic:
- DaoFlow probes from the deployment target host, not from the control plane browser session.
target: "published-port"checks the configured host/port directly from that host.target: "internal-network"resolves the running compose container addresses for the targeted compose service and checks each running replica.- Docker Compose container state and Docker health must pass before the readiness probe can promote the rollout.
- Remote HTTP probes need
curlavailable so the worker can execute the probe over SSH from the host that is actually running the Compose project. - Remote TCP probes use
bashplustimeouton the target host to test raw socket connectivity. - Legacy
healthcheckPathmetadata is still stored for compatibility, but compose services should migrate to explicitreadinessProbeconfiguration becausehealthcheckPathis not executed as a rollout gate.
Environment Variable Injection
DaoFlow injects environment variables from the project's environment configuration into the Compose file using docker compose --env-file:
daoflow env set --env-id env_prod_123 \
--key DATABASE_URL \
--value postgresql://... \
--yes
These are then available in your compose.yaml via ${DATABASE_URL}.
For git-backed Compose deployments, DaoFlow also generates a redacted shell export file so remote SSH execution sees the same resolved build/runtime environment surface as local execution. This is what allows Compose build: services and environment-backed BuildKit secret references to behave consistently on the target host without leaking secret values into logs or persisted plan artifacts.
Preview Lifecycle Automation
Preview-enabled compose services can also reconcile preview stacks directly from provider webhooks when the project has webhook auto-deploy enabled:
- GitHub pushes to non-auto-deploy branches queue branch preview deploys for services that allow branch previews.
- GitHub branch deletion pushes queue branch preview cleanup for the matching shadow environment.
- GitHub pull request
opened,synchronize, andreopenedevents queue preview deploys. - GitHub pull request
closedevents queue preview cleanup. - GitLab merge request
open,update, andreopenevents queue preview deploys. - GitLab merge request
mergeandcloseevents queue preview cleanup.
DaoFlow records each branch or pull-request preview as a durable shadow environment attached to the base service. The shadow environment stores the preview key, branch, PR number when present, env branch, stack name, primary domain, lifecycle status, cleanup state, and latest deployment pointer. Deployment history remains the audit log, but the UI, API, and CLI can list preview environments directly instead of reconstructing them from the latest deployment.
Git Provider Setup
Git-backed Compose projects can be attached to a registered provider during project creation. Register the provider in Git settings, connect the installation or OAuth account, then create the project from the setup wizard, the Projects page, or the CLI with:
- Git provider
- Git installation
- repository full name, such as
acme/api - default branch
- auto-deploy branch
- Compose path, such as
compose.yamlordeploy/compose.yaml
For GitHub App projects, install the app into the target account, select that installation during
project creation, enable webhook auto-deploy when branch pushes should deploy automatically, and
configure preview behavior on the Compose service after the project exists. GitHub pull request
events then drive preview deploy and cleanup for preview-enabled services. GitHub branch pushes that
do not target the project's auto-deploy branch drive branch previews when the service preview mode is
branch or any.
For GitLab.com, register a GitLab provider with the GitLab OAuth app client ID, client secret, and webhook secret. The OAuth callback URL is:
https://<daoflow-host>/settings/git/callback
The webhook URL is:
https://<daoflow-host>/api/webhooks/gitlab
Set the GitLab webhook secret token to the same secret stored on the provider. Use push and merge request events for auto-deploy and preview lifecycle automation.
For self-hosted GitLab, set the provider base URL to the root GitLab URL, for example
https://gitlab.example.com. Use the same callback URL and webhook URL shown above, but create the
OAuth application and webhook inside the self-hosted GitLab instance. DaoFlow uses the provider base
URL when exchanging OAuth codes, validating source access, and matching webhook project URLs, so the
same group/project path can exist safely on GitLab.com and a self-hosted GitLab host.
Preview config can also carry a retention window through staleAfterHours. When set, DaoFlow can compare the latest preview deployment state against observed tunnel-route hostnames and queue Compose preview cleanup for terminal preview stacks that outlive the configured window.
On the service detail page, the Environment tab now shows preview lifecycle state as a first-class operator surface:
- Preview mode, managed domain template, and cleanup retention policy
- Each tracked preview branch or pull request, including stack name and preview env branch
- Whether the preview is active, stale, failed, cleaning, or already cleaned up
- Why DaoFlow is keeping the preview around and what event or action will remove it
- Manual preview retirement plus dry-run or live cleanup execution when the operator has deploy permissions
The CLI exposes the same records with daoflow services previews --service <id> --json. Environment variable inventory can also resolve directly against a shadow environment with daoflow env list --preview-env <id> --json, which applies branch-pattern variables to the preview env branch rather than relying on a caller-supplied branch string.
That UI keeps preview-specific cleanup isolated from the base environment, so clearing a preview does not flatten or mutate the long-lived environment configuration.