Manage Docker Compose stacks as infrastructure with formae.
This plugin provisions and manages Docker Compose projects by shelling out to the docker compose CLI. It supports the full resource lifecycle: create, read, update, delete, and discovery.
Requires the formae CLI: see the quick start.
formae plugin install composeRestart the formae agent afterwards so it loads the plugin.
New project: formae project init --yes my-project creates my-project with a PklProject and a starter main.pkl; then add the compose dependency as for an existing project. Don't run it in an existing project: it overwrites both files.
Existing project: add the plugin to dependencies in your PklProject, with the current version from the hub page, then run pkl project resolve:
["compose"] {
uri = "package://hub.platform.engineering/plugins/compose/schema/pkl/compose/compose@<version>"
}Next: write your first forma, then formae apply (see apply modes).
With an AI coding assistant, use the formae plugin (formerly formae-mcp), which can search the hub and fetch plugin examples. The formae documentation is also available as llms.txt.
| Resource Type | Description |
|---|---|
DOCKER::Compose::Stack |
A Docker Compose project managed via docker compose up/down |
The plugin connects to a Docker daemon. The default configuration uses the local Docker socket:
new formae.Target {
label = "local-docker"
namespace = "DOCKER"
config = new compose.Config {}
}The compose.Config class exposes:
| Field | Default | Description |
|---|---|---|
host |
unix:///var/run/docker.sock |
Docker host URI |
Docker credentials (registry auth, TLS certs) are read from the environment, not from the target config.
The compose.Stack resource has the following fields:
| Field | Type | Mutable | Description |
|---|---|---|---|
projectName |
String |
No (createOnly) | Compose project name, used as native ID. Changing triggers replacement. |
composeFile |
String |
Yes | Compose YAML content. Changes trigger docker compose up. |
endpoints |
Mapping<String, String>? |
Yes | Named endpoint declarations (name -> service:port). Resolved to actual URLs after apply. |
status |
String? |
Read-only | Current project status from Docker. |
A compose.Stack exposes a StackResolvable for cross-plugin references:
local myStack: compose.Stack = ...
// Reference from another resource:
myStack.res.endpoints // resolves to the endpoints mapping
myStack.res.projectName // resolves to the project nameA single nginx container:
formae apply --mode reconcile --watch examples/basic/main.pklGrafana LGTM all-in-one (Loki, Grafana, Tempo, Mimir) with OpenTelemetry collector:
formae apply --mode reconcile --watch examples/lgtm/main.pklLicensed under FSL-1.1-ALv2. See LICENSE.