Docker Compose

Docker Compose

It helps you configuring and starting multi-container applications.

Compose simplifies the control of the entire application stack, facilitating the management of services, networks and volumes in a single YAML configuration file (usually compose.yaml). And with simple Compose CLI commands you can bring UP or DOWN an entire container network.

Compose How-tos

You may also use fragments and extensions to keep your Compose files easy to maintain.

These muliple Compose files can be merged together to define the application model.

docker compose -f angular-compose.yaml -f node-compose.yaml.

It merges files in the order they are specified on the command line. Subsequent files may merge, override, or add to their predecessors.

  • Meaning that if a service with the same name is in two different merging files, their configurations might be overriden or added.

    • For single-value options the value is replaced.

    • For multi-value options the values are added.

    • For <key> <value> options, the values might get added or overwritten.

    • For volumes and devices, values are merged using the mount path in the container.

Compose automatically searches on the same folder and parent folder for compose.yaml and compose.override.yaml and merges them by default.

You can also supply configurations from the STDIN with - after -f:

To easy modularize complex applications into sub-Compose files. Each path listed in the include section loads as an individual Compose application model, with it's own project directory, in order to resolve relative paths.

Override services

Compose reports an error if any resource from include conflicts with resources from the included Compose file.

So, to tweak configurations from the included file you add an override file to the include directive, for overwriting specific files.

Or, if you need to override multiple files and don't want to create multiple override files, you may create a single global compose.override.yaml file.

Useful for reusing service options, from other files or from the same file.

Relative paths are automatically adjusted.

When Docker Compose runs a container, it uses ENTRYPOINT and CMD to manage what happens when the containers starts and stops.

In Compose you may handle these separatly with lifecycle hooks - (commands that run right after the container starts or just before it stops).

Lifecycle hooks also have special privileges (like running as the root user), even when the container itself runs with lower privileges for security.

Post-start hooks

Commands that runs right after a container starts.

Pre-stop hooks

Commands that runs before the container stops. (docker compose down or manually with Ctrl+C)

profiles help you adjust your Compose application for different environments or use cases, by selectively activating services.

Services without profiles are always enabled.

Core services of your application shouln't be assigned profiles so they are always enabled and automatically started.

Starting profiles

Targeted services from depends_on should either:

  • Share a common profile.

  • Or not have profiles set.

Starting specific profiles (--profile)

Stopping specific profiles

It follows the same logic as starting profiles.

Compose always starts and stops containers in dependency order, where dependencies are determined by:

  • depends_on

  • links

  • volumes_from

Detecting "ready" states

Use the condition attribute with one of the following:

  • service_started

  • service_healthy: A dependency is expected to be "healthy", which is defined by healthcheck.

  • service_completed_successfully: A dependency is expected to run to successful completion before starting a dependent service.

In this case:

  1. db and redis are created first.

  2. Then Compose waits for healthchecks to pass on db.

    • Healthcheck is done with pg_isready, retried every 10 seconds up to 5 times.

  3. Then it creates web.

When both env_file and environment are set for a service, values set by environment have precedence.

Check the precedence order here.

You can also temporarily set them on.

Are any piece of data, such as password, certificates, or API keys that shouln't be transmitted over a network or stored unencrypted in a Dockerfile or the applications's source code.

Compose grants access to secrets on a per-service basis.

Env variables are often available to all processes, and can be difficult to track access.

They can also be printed in logs.

When communicating between services (containers), note that you must use the CONTAINER_PORT and not the HOST_PORT.

Configuring the Default network

You can alias the service's name for extra ways to connecting to the container.

This way, you can access the db service from app by the either [db, database].

Creating Custom Networks

To create more complex topologies and specify different network drives and options. Also to connect services to externally-created networks which aren't managed by Compose.

Each service may specify one or more networks to connect to.

Joining External Networks

Compose CLI

The docker compose has a couple of flags that can be used.

Flag
Description

--dry-run

Execute commands in dry run mode.

--env-file

Specify an alternate environment file.

-f or --file

Compose configuration files.

--progress

Set thype of progress output. (auto, tty, plain, json, quiet)

--project-directory

Specify an alternate working directory. (default: the path of the, first specified, Compose file)

-p or --project-name

Project name. (/^[a-z0-9]+[a-z0-9\-\_]*/)

docker compose down [OPTIONS] [SERVICES]

Will stop and remove the following, that were created by up :

  • Containers;

  • Networks:

    • The ones defined in network section of compose.yaml.

    • Networks defined as external are never removed.

  • Volumes:

    • Anonymous volumes are not removed by default. (But are also not mounted for subsequent up)

    • Volumes defined as external are never removed.

  • Images if flag --rmi used.

Flag
Description

--remove-orphans

Remove containers for services not defined in the Compose file.

--rmi

Removes Images used by services. ("local" remove only images that don't have a custom tag ("local" | "all"))

-t or --timout

Specify a shutdown timout in seconds.

-v or --volumes

  • Removes named volumes declared in the volumes section of the Compose file.

  • Removes anonymous volumes attached to containers.

docker compose logs [OPTIONS] [SERVICES]

Display log outputs from services.

docker compose ps [OPTIONS] [SERVICE]

List containers for a Compose project, with current status and exposed ports.

By default, only running containers are shown.

Flag
Description

-a or --all

Show all containers. (Including the ones created without Compose)

--format

Format output with custom template. (table, json, TEMPLATE)

--orphans

Include services not declared by project.

docker compose run [OPTIONS] SERVICE [COMMAND] [ARGS...]

Runs a one-time command against a service.

docker compose up [OPTIONS] [SERVICES]

Builds, (re)creates, starts and attaches to containers for a service.

If there are existing containers for a service and it's Images or service's configuration were changed, up will detect the changes and recreate the containers (preserving mounted volumes).

To avoid recreation of containers use --no-recreate flag.

To force recreation of all containers use --force-recreate flag.

Flag
Description

--abort-on-container-exit

Stop all containers if any container was stopped. (Incompatible with -d)

--abort-on-container-failure

Stop all container if any container exited with failure. (Incompatible with -d)

--build

Build Images before starting containers.

-d or --detach

Run containers in the background.

--force-recreate

Recreate containers even if their configuration and Image haven't changed.

--no-attach

Do not attach (stream logs) to specified services.

--no-deps

Do not recreate services linked services. Ex.: If you change a service config, and don't need to rebuild the dependent services.

--no-recreate

Don't recreate containers even if their configuration and Image have changed.

--no-start

Don't start the services after creating them.

--quiet-pull

Pull images without printing progress information.

-V or --renew-anon-volumes

Recreate anonymous volumes instead of retrieving data from the previous containers.

--timestamps

Show timestamps.

--wait

Wait for services to be running|healthy. (Implies detached mode)

--wait-timeout

Maximum duration to wait for project to be running|healthy.

Running

  • You can run the docker-compose with docker-compose up.

    • Use -d to run in detach mode.

  • You can choose the services/container to go up with:

    • docker-compose up [list-of-container], like docker-compose up -d node mysql.

Stopping

  • You can stop the containers with docker-compose down.

  • Docker compose will stop and remove the containers, networks and others, BUT NOT the volumes that were created.

    • Use -v flag to also delete the volumes.

Choosing a dockerfile from multiple ones

Dependency of Containers

  • You can specify that a container should only go up if another one went up with depends_on config.

  • This means that if you start with docker-compoase up -d frontend, it will automatically up the backend container.

Force docker-compose to reevalute the dockerfiles and rebuild if necessary

Front end Containers

  • Just like it was needed to use the flag -it in frontend containers, you can config them with:

YAML Tips & Tricks

Some YAML tips when creating the Compose files.

Are built-in YAML features, to help create re-usable blocks. (They kind of work like variables, not really..)

From this example, you configure and name the properties from environment as &env (where & symbol states the origin of data), and then reuse them later with *env.

Adding or Overriding values

Pulling more than one anchor

Use the prefix x- as a top-level element to modularize configurations to reuse.

Compose ignores any fields that starts with x-.

This means that you can use it to declare properties on the top of the file (like variables), and then use them inside valid properties (services, networks, ...) with anchors.

Values in Compose file can be set by variables and interpolated at runtime.

Both $VARIABLE and ${VARIABLE} are supported.

Compose Properties

Some of the top-level properties that can be defined in compose.yaml.

To define the project's name. Can also be set by COMPOSE_PROJECT_NAME default env variable or by -p option in the command line.

service (required)

A service is an abstract definition of a computing resource, and is backed by a container.

Specify byte values like {amount}{byte unit}, where {byte unit} may be:

b (bytes), k or kb (kilo bytes), m or mb (mega bytes) and g or gb (giga bytes)

Ex.: 300m or 2gb.

Specify durations like {value}{unit}, {unit} may be:

us (microseconds), ms (milliseconds), s (seconds), m (minutes) and h (hours)

Ex.: 40s, 1m30s, 1h30m50s20ms.

Some attributes a service may declare:

Property
Type
Description

value

Defines how to create the Docker image for the service. (Usually the path to the Dockerfile)

blkio_config

map

Defines a set of configurations to set IO block limits.

cap_add

array

Additional container capabilities.

command

value

Overrides the default command declared by the container image. (Ex.: By Dockerfile's CMD) (If value is '' or [], default command is overwriten to be empty)

container_name

value

For custom container's name. (If defined, may stop Compose from scaling beyond one container)

cpu_count

value

Defines the number of usable CPUs.

cpu_shares

value

As integer value, defines relative CPU weight versus other containers.

array or map

To define dependency to other services. Will also control the order of startup and shutdown.

map

Set of deployment specifications for managing the behavior of containers across different environments.

domainname

value

Custom domain name for the container.

entrypoint

value or array

Overrides the default entrypoint declared by the container image. (Ex.: By Dockerfile's ENTRYPOINT) (If value is '' or [], default command is overwriten to be empty)

value, array or map

Specify one or more files that contain env variables.

array or map

To list env variables.

map

Share common configurations among services.

extra_hosts

array or map

Adds hostname mappings to container's network interface configuration. Ex.: (/etc/hosts)

map

Declares a check to determine if the service containers are "healthy".

hostname

value

Custom hostname for the container.

image

value

Another way to define which image to use. (Like if you don't have a Dockerfile)

array

Network link aliases to services in another container. (Ex.: SERVICE:ALIAS)

mem_limit

value

Limit the amount of memory a container can allocate.

Ex.: (300m, 1gb) (Must be consistent with limits.memory attribute in deploy attribute)

mem_reservation

value

Reserves an amount of memory a container can allocate.

Ex.: (300m, 1gb) (Must be consistent with reservations.memory attribute in deploy attribute)

value

Sets the container network mode. (none, host, service:{name}, container:{name})

array or map

Defines the networks the service is attached to.

value or array

Define port mapping between host and container (host:container).

privileged

value

Configures the service to run with elevated priviledges.

array or map

Defines the list of named profiles for the service to be under.

value

Defines the restart policy on container termination.

array

List of variables for sensitive data. Reference top-evel secrets or create local ones.

tty

value

Configure the service to run with tty. (Same as running the container with -t flag.

user

value

Overrides the user to run the container process. (This overwrites the user defined in Dockerfile)

array

Define mount host paths or named volumes assessible by the containers. (For the volume to be reused by multiple services, it must also be declared as top-level)

working_dir

value

Overrides the container's working directory. (This overrides WORKDIR from Dockerfile)

Check more info over Network up here.

The top-level networks lets you configure named networks that can be reused across multiple services.

Some attributes a service may declare:

Property
Type
Description

driver

value

Specifies the network driver to use.

external

value

Specifies if the network is maintained outside the application.

map

To configure more in-depth options for the network.

name

value

Custom name for the network.

The top-level volumes lets you configure named volumes that can be reused across multiple services.

Some attributes a service may declare:

Property
Type
Description

driver

value

Specifies the volume driver to use.

external

value

Specifies if the volume is maintained outside the application.

name

value

Custom name for the volume.

Lets services to adapt their behavior withtout the need to rebuild the Docker Image.

Check more info on the docs.

Check more info over Secrets up here.

The top-level secrets lets you define or reference sensitive data that can be accessed across multiple services.

A secret's source can be either a file or environment.

Last updated