Book Image

A Developer's Essential Guide to Docker Compose

By : Emmanouil Gkatziouras
Book Image

A Developer's Essential Guide to Docker Compose

By: Emmanouil Gkatziouras

Overview of this book

Software development is becoming increasingly complex due to the various software components used. Applications need to be packaged with software components to facilitate their operations, making it complicated to run them. With Docker Compose, a single command can set up your application and the needed dependencies. This book starts with an overview of Docker Compose and its usage and then shows how to create an application. You will also get to grips with the fundamentals of Docker volumes and network, along with Compose commands, their purpose, and use cases. Next, you will set up databases for daily usage using Compose and, leveraging Docker networking, you will establish communication between microservices. You will also run entire stacks locally on Compose, simulate production environments, and enhance CI/CD jobs using Docker Compose. Later chapters will show you how to benefit from Docker Compose for production deployments, provision infrastructure on public clouds such as AWS and Azure, and wrap up with Compose deployments on said infrastructure. By the end of this book, you will have learned how to effectively utilize Docker Compose for day-to-day development.
Table of Contents (19 chapters)
1
Part 1: Docker Compose 101
6
Part 2: Daily Development with Docker Compose
12
Part 3: Deployment with Docker Compose

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.