4.5 KiB
About
The Compose application model defines service
as an abstraction for a computing unit managing (a subset of)
application needs, which can interact with other service by relying on network(s). Docker Compose is designed
to use the Docker Engine ("Moby") API to manage services as containers, but the abstraction could also cover
many other runtimes, typically cloud services or services natively provided by host.
The Compose extensibility model has been designed to extend the service
support to runtimes accessible through
third-party tooling.
Architecture
Compose extensibility relies on the provider
attribute to select the actual binary responsible for managing
the resource(s) needed to run a service.
database:
provider:
type: awesomecloud
options:
type: mysql
size: 256
provider.type
tells Compose the binary to run, which can be either:
- Another Docker CLI plugin (typically,
model
to rundocker-model
) - An executable in user's
PATH
If provider.type
doesn't resolve into any of those, Compose will report an error and interrupt the up
command.
To be a valid Compose extension, provider command MUST accept a compose
command (which can be hidden)
with subcommands up
and down
.
Up lifecycle
To execute an application's up
lifecycle, Compose executes the provider's compose up
command, passing
the project name, service name, and additional options. The provider.options
are translated
into command line flags. For example:
awesomecloud compose --project-name <NAME> up --type=mysql --size=256 "database"
Note:
project-name
should be used by the provider to tag resources set for project, so that later execution withdown
subcommand releases all allocated resources set for the project.
Communication with Compose
Providers can interact with Compose using stdout
as a channel, sending JSON line delimited messages.
JSON messages MUST include a type
and a message
attribute.
{ "type": "info", "message": "preparing mysql ..." }
type
can be either:
info
: Reports status updates to the user. Compose will render message as the service state in the progress UIerror
: Let's the user know something went wrong with details about the error. Compose will render the message as the reason for the service failure.setenv
: Let's the plugin tell Compose how dependent services can access the created resource. See next section for further details.debug
: Those messages could help debugging the provider, but are not rendered to the user by default. They are rendered when Compose is started with--verbose
flag.
sequenceDiagram
Shell->>Compose: docker compose up
Compose->>Provider: compose up --project-name=xx --foo=bar "database"
Provider--)Compose: json { "info": "pulling 25%" }
Compose-)Shell: pulling 25%
Provider--)Compose: json { "info": "pulling 50%" }
Compose-)Shell: pulling 50%
Provider--)Compose: json { "info": "pulling 75%" }
Compose-)Shell: pulling 75%
Provider--)Compose: json { "setenv": "URL=http://cloud.com/abcd:1234" }
Compose-)Compose: set DATABASE_URL
Provider-)Compose: EOF (command complete) exit 0
Compose-)Shell: service started
Connection to a service managed by a provider
A service in the Compose application can declare dependency on a service managed by an external provider:
services:
app:
image: myapp
depends_on:
- database
database:
provider:
type: awesomecloud
When the provider command sends a setenv
JSON message, Compose injects the specified variable into any dependent service,
automatically prefixing it with the service name. For example, if awesomecloud compose up
returns:
{"type": "setenv", "message": "URL=https://awesomecloud.com/db:1234"}
Then the app
service, which depends on the service managed by the provider, will receive a DATABASE_URL
environment variable injected
into its runtime environment.
Note: The
compose up
provider command MUST be idempotent. If resource is already running, the command MUST set the same environment variables to ensure consistent configuration of dependent services.
Down lifecycle
down
lifecycle is equivalent to up
with the <provider> compose --project-name <NAME> down <SERVICE>
command.
The provider is responsible for releasing all resources associated with the service.
Examples
See example for illustration on implementing this API in a command line