Understanding how Docker Compose works
Since we have Docker and Docker Compose installed onto our system, let’s take some time and understand what Compose is and how it works behind the scenes.
On GitHub, we can find a project (https://github.com/docker/compose) where the Docker Compose source code is being hosted. By navigating to the source code, we can see and understand more about Compose, as follows:
- Compose integrates with the Docker CLI as a plugin.
- Compose interacts with Docker Engine through the API.
- Compose provides a CLI and its actions translate into Docker Engine API calls.
- Compose will read the Compose YAML file and generate resources accordingly.
- Compose provides a layer for converting
docker-compose
commands into CLI-compliant ones. - Compose will interact with Docker objects and distinguish between them using labels.
The Docker CLI provides an API to create and load plugins. Once a plugin has been created and loaded on its invocation, the CLI command will be passed to it:
func pluginMain() { plugin.Run(func(dockerCli command.Cli) *cobra.Command { … } } func main() { if commands.RunningAsStandalone() { os.Args = append([]string{"docker"}, compatibility.Convert(os.Args[1:])...) } pluginMain() }
The CLI is based on Cobra (https://github.com/spf13/cobra), which is a popular Go library for CLI applications.
Compose, being a plugin of the Docker CLI, will use a Docker Engine API client provided by the Docker CLI:
lazyInit.WithService(compose.NewComposeService(dockerCli.Client(), dockerCli.ConfigFile()))
Each command passed to the Docker Compose plugin will lead to an interaction with the Docker Engine API on our host. For example, the internals of the ls
command:
func (s *composeService) List(ctx context.Context, opts api.ListOptions) ([]api.Stack, error) { list, err := s.apiClient.ContainerList(ctx, moby.ContainerListOptions{ Filters: filters.NewArgs(hasProjectLabelFilter()), All: opts.All, }) if err != nil { return nil, err } return containersToStacks(list) }
We now have a good understanding of how Compose works and interacts with Docker Engine. You can also refer to the source code for more information. Next, we’re going to run our first Docker Compose application.