Write a project manifest
Create a YAML file that describes your workload. At minimum you need The fields you can set in
apiVersion, kind, metadata.name, and at least one service under spec.services.project.yaml
spec:| Field | Required | Description |
|---|---|---|
services | Yes | Ordered list of containers to run. |
services[].name | Yes | Service name — also the DNS hostname inside the bridge network. |
services[].image | Yes | Docker image reference, e.g. postgres:15. |
services[].env | No | Environment variables injected at container start. |
services[].volumeMounts | No | Named volumes to mount into the container. |
volumes | No | Named volume definitions shared across services. |
ingress | No | HTTP routing rules for internal traffic. |
expireAt | No | RFC 3339 timestamp after which the GC controller deletes the project. |
Multi-service example: WordPress
The following manifest runs MySQL and WordPress together. Theapp service
reaches the database using the hostname db — resolved automatically over the
shared bridge network.wordpress.yaml
Ephemeral is currently the only supported volume type. Ephemeral volumes are discarded when the project is stopped or moved to a different node.Apply the manifest
Run You should see output like:
caractrl apply to send the manifest to the control plane. The API server creates the project record and sets its initial phase to Pending.Watch the phase change
Poll the project status to track its progress through the lifecycle:Example output:The
PHASE column reflects the current lifecycle state:| Phase | Set by | Meaning |
|---|---|---|
Pending | Server | Accepted by the API; the scheduler has not yet chosen a node. |
Scheduled | Scheduler | A node has been assigned; the agent has not confirmed containers are up. |
Running | Agent | All containers are running. |
Failed | Agent | The agent could not start the project or reported a terminal error. |
Terminating | Server | A deletion request was received; the agent is tearing down containers. |
Terminated | Agent | All containers and Docker resources have been removed. |
Check conditions if something goes wrong
If your project stays in Look for the Each condition has a
Pending or moves to Failed, inspect the conditions array for a detailed reason. Use --output json to see the full status object:status.conditions array in the output:type, status (True / False), a machine-readable reason, and a human-readable message.View the assigned node
Once the scheduler picks a node, Use the node name to inspect that node’s capacity and health:
status.nodeRef is populated with the node name. You can see it in the JSON output:Clean up
Delete a project when you no longer need it. The control plane transitions the project to If the agent acknowledges the teardown synchronously, you see:Otherwise you see:In either case, the project disappears from the list once the agent sets the phase to
Terminating and signals the agent to tear down all containers, networks, and volumes.Terminated and the termination controller removes the record.Common issues
Project stays Pending
Project stays Pending
The scheduler only assigns work to nodes in the If all nodes are
Ready state. If no ready nodes exist in the cluster, the project waits indefinitely.Check your node states:NotReady, verify that cara-agent is running on at least one machine and that its heartbeats are reaching the control plane. See Node management for details.Project moves to Failed
Project moves to Failed
A Fix the underlying issue, then delete and re-apply the project — there is no in-place restart.
Failed phase means the agent encountered a terminal error it cannot recover from on its own. The most common causes are:- Image pull failure — the image name or tag is wrong, or the registry is unreachable from the node.
- Port conflict — another container on the node already occupies a required host port.
- Volume error — the Docker daemon could not create the volume.
Ephemeral environments with spec.expireAt
Set spec.expireAt to an RFC 3339 timestamp to create a project that the GC controller automatically deletes after that time. This is useful for preview or CI environments that should not outlast a fixed window.
caractrl delete project pr-preview-42.