Operate
Compose Attachments
How attachments.compose works, how it differs from compose:up, and how to keep workload containers and Compose-managed services on the same truthful network boundary.
Recommended next
Why this feature exists
attachments.compose lets an Ota-managed workload container join one or more Compose project networks without forcing Docker to run inside the app image.
That is the right model when Compose stays on the host control plane, but app tasks should still reach Compose-managed services by service name from inside their own container context.
- Compose is still started and stopped from the host
- the workload task still runs in its own Ota-managed container context
- the workload container joins the Compose network namespace declared by the attachment
- service reachability becomes truthful from the workload plane instead of being faked through host ports or Docker-in-Docker
What it is and what it is not
attachments.composeis a network attachment declaration for container contexts- it is not a replacement for
compose:upor a service manager declaration - it does not start Compose services by itself
- it does not mean the task runs inside the Compose service container
Use attachments.compose on the workload context when that workload container should join the Compose project network.
execution: default_context: app contexts: host: backend: native requirements: tools: docker: "*" app: backend: container lifecycle: persistent container: image: maven:3.9.14-eclipse-temurin-21-noble attachments: compose: - qredex-coreThe most important alignment rule
Keep attachments.compose aligned with the Compose project name used by the related service managers.
If those names drift, Ota attaches the workload container to the wrong network family and service-name reachability breaks.
The workload context and the typed Compose service manager both use the same project name: qredex-core.
execution: contexts: app: backend: container attachments: compose: - qredex-core services: postgres: manager: kind: compose name: qredex-core file: docker-compose.yml service: postgresHow it differs from compose:up
compose:up is a host task that controls the Compose project lifecycle.
attachments.compose is a workload-context declaration that tells Ota which Compose network family the workload container should join.
- use
compose:upwhen the host should start the service stack - use
attachments.composewhen the app container should join that stack's network - use both together when the repo truthfully splits host orchestration from container workload execution
This is the common split: host tasks own Compose commands, app tasks run in a container context that joins the Compose network.
tasks: compose:up: context: host run: docker compose up -d postgres compose:down: context: host run: docker compose down -v db:integration: context: app requires_services: - postgres run: mvn -B -Dgroups=db-integration testCanonical use case
This is the qredex-core shape: Compose owns Postgres on the host, while the Java app and tests run in an Ota-managed container that should reach postgres:5432 directly.
The goal is honest network topology, not a flattened host-port workaround.
The workload reaches Postgres by service name from inside the attached container context.
version: 1project: name: qredex-core execution: default_context: app contexts: host: backend: native requirements: tools: docker: "*" app: backend: container lifecycle: persistent container: image: maven:3.9.14-eclipse-temurin-21-noble attachments: compose: - qredex-core services: postgres: manager: kind: compose name: qredex-core file: docker-compose.yml service: postgres endpoints: app: address: postgres port: 5432 readiness: from: app run: pg_isready -h postgres -p 5432When to use it
- use it when Compose services should be controlled from the host but reached by service name from a container workload context
- use it when the repo should stay honest about host orchestration versus workload execution
- use it when the right answer is a shared network boundary, not a guessed host alias or published port workaround
What not to do
- do not use Docker inside the app image as the main model
- do not treat published host ports as the primary in-container reachability path when service-name networking is the real topology
- do not let
attachments.composeandservices.<name>.manager.namedrift apart - do not confuse Compose attachments with shared backends; one is network attachment, the other is backend-boundary reuse