cpln stack command deploys Docker Compose projects directly to Control Plane, automatically converting services, volumes, secrets, and networks to their Control Plane equivalents.
When to use this
Migrate from Docker Compose
Move existing Compose projects to Control Plane without rewriting configuration
Local-to-cloud workflow
Develop locally with Compose, deploy to Control Plane for production
Multi-service apps
Deploy interconnected services as a cohesive stack
Preview deployments
Generate and inspect Control Plane manifests before deploying
Prerequisites
CLI installed
CLI installed
Install the Control Plane CLI. See Installation.
Docker Compose project
Docker Compose project
You need a
docker-compose.yml or compose.yaml file.Required permissions
Required permissions
You need permissions to create workloads, secrets, volumesets, identities, and push images.
Deploy a project
Delete a project
Remove all resources created by a Compose deployment:Preview the generated manifests
Generate Control Plane specs without deploying:Customize workloads with x-cpln
Add anx-cpln block to any service to override the generated workload spec. Each top-level key in x-cpln replaces the corresponding section in the workload spec:
docker-compose.yml
Available overrides
| Key | Description |
|---|---|
type | Workload type: serverless, standard, stateful |
containers | Complete container specifications |
defaultOptions | Autoscaling, capacity AI, timeouts, suspend |
firewallConfig | External and internal firewall rules |
identityLink | Link to a specific identity |
supportDynamicTags | Enable dynamic image tag detection |
loadBalancer | Load balancer configuration |
rolloutOptions | Deployment rollout strategy |
securityOptions | Security context settings |
localOptions | Location-specific overrides |
Service-to-service communication
Update service URLs to use the Control Plane local syntax:{GVC} with your actual GVC name.
See the Service-to-Service guide for the full endpoint syntax.
How workload type is determined
The converter analyzes your service definition to select the appropriate workload type:| Condition | Workload Type |
|---|---|
| Service has volumes attached | stateful |
| Service exposes exactly one port | serverless |
| Service exposes multiple ports or no ports | standard |
Translation reference
Resource mapping
| Compose Field | Control Plane Equivalent |
|---|---|
deploy.resources.limits.cpus | Container CPU (multiplied by 1000 for millicores) |
deploy.resources.limits.memory | Container memory |
deploy.replicas | minScale and maxScale (set to same value) |
healthcheck | Readiness probe |
ports / expose | Container ports |
environment / env_file | Environment variables (env_file processed first, environment has precedence) |
working_dir | Container working directory |
command | Container args |
entrypoint | Container command |
Port protocol
Specify the protocol directly in the port string:Defaults
| Property | Default Value |
|---|---|
| CPU | 42m |
| Memory | 128Mi |
| External inbound | Allowed if ports defined |
| External outbound | Allowed (unless network_mode: none) |
| Capacity AI | Enabled only if: reservations < limits, no GPU, and not stateful |
Secrets and configs
Bothsecrets and configs are converted to Control Plane secrets:
- Default mount path:
/run/secrets/{name}(if no absolute path specified) - Identities and policies are automatically created for workloads using secrets
Healthcheck conversion
Docker healthchecks are converted to readiness probes:| Compose Field | Control Plane Field |
|---|---|
test | exec.command |
interval | periodSeconds |
timeout | timeoutSeconds |
start_period | initialDelaySeconds |
retries | failureThreshold |
- String:
"curl http://localhost/health"→/bin/sh -cwrapper - CMD:
['CMD', 'curl', 'http://localhost']→ direct execution - CMD-SHELL:
['CMD-SHELL', 'curl http://localhost']→/bin/sh -cwrapper - NONE: Disables the readiness probe
Network modes
| Mode | Behavior |
|---|---|
| Default (no networks) | All services can reach each other |
| Named networks | Only services in the same network can communicate |
network_mode: host | External inbound traffic allowed |
network_mode: none | No outbound traffic allowed |
network_mode: service:other | Shares network with another service |
GPU support
Services with GPU devices are automatically configured:- NVIDIA T4 GPU
- Minimum CPU:
2000m(overrides default) - Minimum Memory:
7168Mi(overrides default) - Capacity AI: Disabled
Service inheritance
Extend services from the same or different compose files:Limitations
| Feature | Status | Alternative |
|---|---|---|
| Directory bind mounts | Not supported | Use named volumes or file bind mounts |
depends_on ordering | Ignored | Services start independently; use health checks |
links | Ignored | Use network-based service discovery |
| Dynamic GPU model/quantity | Limited | Hardcoded to NVIDIA T4, quantity 1 |
| Multiple containers per service | Not supported | Create separate services |
privileged mode | Not supported | Use securityOptions via x-cpln |
Troubleshooting
Service-to-service connection fails
Service-to-service connection fails
Update hostnames to use the Control Plane local syntax:Ensure both services are in the same network or no networks are defined (global network).
Ports not accessible
Ports not accessible
Ensure all ports are explicitly listed in
ports or expose in your Compose file. Only services with ports defined get external inbound access.Secret not found
Secret not found
Secrets referenced in Compose are converted to Control Plane secrets. The converter automatically creates identities and policies. Check that:
- The secret file exists at the specified path
- You have permissions to create secrets, identities, and policies
Directory bind mount error
Directory bind mount error
Directory bind mounts are not supported. Convert to either:
- Named volumes (for persistent data)
- File bind mounts (for configuration files → converted to secrets)
Both image and build specified
Both image and build specified
A service cannot have both
image and build specified. Use one or the other:image: Pull from a registrybuild: Build and push to Control Plane registry
Services can't communicate
Services can't communicate
By default, all services can reach each other. If you’re using named networks, ensure communicating services are in the same network.