# Docker Compose

{% embed url="<https://docs.docker.com/compose/>" %}
Docker Compose
{% endembed %}

## [How Compose Works](https://docs.docker.com/compose/intro/compose-application-model/)

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.

{% hint style="warning" %}
`docker-compose.yaml` and `docker-compose.yml` are also reconized ONLY for backward compatibility.

Use `compose.yaml`.
{% endhint %}

{% hint style="danger" %}
`compose.yaml` doesn't replace the Dockerfile.

*Not all of the configurations in Dockerfile can be done in the* `compose.yaml`*.*
{% endhint %}

## Compose How-to's

### [Using multiple Compose `.yaml` files](https://docs.docker.com/compose/gettingstarted/#step-7-split-up-your-services)

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.

#### [Merging them with `-f`](https://docs.docker.com/compose/how-tos/multiple-compose-files/merge/)

`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.

{% hint style="danger" %}
Some rules for merging files:

* Make sure all paths in the files are relative to the base Compose file (the first file specified with `-f` on the command line)
  * Use `docker compose config` to review your merged configuration.
    {% endhint %}

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`:

```bash
# Reading properties from the STDIN
docker compose -f - <<EOF
webapp:
 image: ubuntu
 # ...
EOF
```

#### [`include` other Compose files](https://docs.docker.com/compose/how-tos/multiple-compose-files/include/)

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.

```yaml
include:
  - other-compose-file.yaml
services:
  serviceA:
    build: .
    dependes_on:
      # Just call it as it was in the same file
      - serviceB
```

**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.

```yaml
include:
  - path:
    - other-compose-file.yaml
    - override.yaml
```

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.

{% code title="compose.yaml" %}

```yaml
include:
  - team-1/compose.yaml
  - team-2/compose.yaml
```

{% endcode %}

{% code title="compose.override.yaml" %}

```yaml
services:
  service-1:
    ports:
      - 40:40
  service-2:
    volumes:
      - ./src:./src
```

{% endcode %}

#### [`extends` in Compose files](https://docs.docker.com/compose/how-tos/multiple-compose-files/extends/)

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

```yaml
services:
  web:
    extends:
      file: common-services.yml
      service: webapp
    # OR
    # IF `webapp` is inside this file
    extends: webabb
```

{% hint style="danger" %}
`volumes_from` and `depends_on` are never shared, to avoid implicit dependencies.
{% endhint %}

{% hint style="info" %}
Relative paths are automatically adjusted.
{% endhint %}

### [Compose Lifecycle Hooks](https://docs.docker.com/compose/how-tos/lifecycle/)

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.

```yaml
services:
  APP:
    post_start:
      - command: COMMAND
        user: root
```

#### Pre-stop hooks

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

{% hint style="danger" %}
These hooks won't work if the container stops by itself or gets killed suddently.
{% endhint %}

```yaml
services:
  APP:
    pre_stop:
      - command: COMMAND
```

### [Service Profiles](https://docs.docker.com/compose/how-tos/profiles/)

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

{% hint style="info" %}
Services without `profiles` are always enabled.

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

```yaml
# Running a `docker compose up` here will only start `backend` and `db` services
services:
  frontend:
    image: frontend
    
  phpmyadmin:
    image: phpmyadmin
    depends_on: [db]
    profiles: [debug]
  
  backend:
    image: backend
    profiles: [backend]
    depends_on:
      - db
    
  db:
    image: mysql
    profiles: [backend]
```

#### Starting profiles

```bash
# Only [frontend] will start
docker compose up

# [frontend, backend, db] will start
docker compose up --profile backend

# Will fail because `phpmyadmin` depends on `db`, but because they are from different profiles, `db` does not get started.
# Possible correction would be to add `debug` profile to `db` OR remove all profiles from `db`.
docker compose up --profile phpmyadmin

# Will call for start only `backend`, but since it depends on `db` it will also start it.
docker compose run backend

# Agina it will call for start only `phpmyadmin`, but this time it will fail, since it depends on `db` but db is in a different profile.
# Possile correction would be to add `debug` profile to `db` OR remove all profiles from `db`.
docker compose run phpmyadmin
```

{% hint style="info" %}
Targeted services from `depends_on` should either:

* Share a common profile.
* Or not have `profiles` set.
  {% endhint %}

#### Starting specific profiles (`--profile`)

```bash
# Start a single profile
docker compose --profile debug up
```

```bash
# Start multiple profiles
docker compose --profile debug --profile backend up
```

```bash
# Start with ALL 
docker compose --profile "*" up
```

#### Stopping specific profiles

It follows the same logic as starting profiles.

```bash
docker compose --profile debug down
```

### [Controlling startup order](https://docs.docker.com/compose/how-tos/startup-order/)

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

* `depends_on`
* `links`
* `volumes_from`

{% hint style="danger" %}
BUT, Compose does not wait until a container is "**ready**", only until it's **running**.

*This may cause issues if services running inside the container triggers other services that might take some time to start but are critical operationaly speaking.*
{% endhint %}

### 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.

```yaml
services:
  web:
    build: .
    depends_on:
      db:
        condition: service_healthy
        restart: true
      redis:
        condition: service_started
  redis:
    image: redis
  db:
    image: postgres
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
      interval: 10s
      retries: 5
      start_period: 30s
      timeout: 10s
```

**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`.

### [Environment Variables](https://docs.docker.com/compose/how-tos/environment-variables/set-environment-variables/)

{% hint style="danger" %}
Don't use `env` variables to pass sensitive information, use [`secrets`](https://docs.docker.com/compose/how-tos/use-secrets/) instead.
{% endhint %}

{% hint style="warning" %}
Compose relies on you to resolve the values. Un-resolved values will lead to the variable being unset and removed.

No warning is raised. (Unless [`interpolation`](https://docs.docker.com/compose/how-tos/environment-variables/variable-interpolation/) is used)
{% endhint %}

```yaml
services:
  app:
    environment:
      # Map syntax:
      # Any boolean values (true, false, yes, no) should be enclosed by quotes to ensure
      # they won't be converted by YAML parser.
      TYPE: development
      DEBUG: "true"
      # Variables without values are expected to be given a value at run-time.
      USER_INPUT:

      # OR
      
      # Array syntax:
      - TYPE=development
      - DEBUG=true
      - USER_INPUT
      
    # OR
    
    # To declare one or more .env files. (If multiple files, they are evaluated in
    # order, and one can overwrite values from the previous)
    # The path is relative to the `compose.yaml` file.
    env_file: "app.env"
```

{% hint style="info" %}
When both `env_file` and `environment` are set for a service, values set by `environment` have precedence.

Check the precedence order [here](https://docs.docker.com/compose/how-tos/environment-variables/envvars-precedence/).
{% endhint %}

You can also temporarily set them on.

```bash
docker compose run --env USER_INPUT="Some Value" --env DEBUG="false"
```

### [Secrets](https://docs.docker.com/compose/how-tos/use-secrets/)

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.

{% hint style="info" %}
`Env` variables are often available to all processes, and can be difficult to track access.

They can also be printed in logs.
{% endhint %}

```yaml
# Providing secrets inside files
services:
  app:
    image: myapp:latest
    secrets:
      - some_secret
      
secrets:
  some_secret:
    file: ./secret_pass.txt
```

```yaml
# Feeding secret from build-time ENV variables
services:
  app:
    image: myapp:latest
    secrets:
      - some_token
      
secrets:
  some_token:
    environment: TOKEN
```

### [Network](https://docs.docker.com/compose/how-tos/networking/)

{% hint style="warning" %}
By default Compose sets up a single network for your application.

* *The network's name is given based on the project's name, which is based on the name of the directory it lives in OR the project's name given by* `--project-name`.

Each container for a service joins the default network and is both reachable by other container on that network, and discoverable by the **service's name**.

* *This means instead of using the container's name, like it was done with* `docker run`, *with* `docker compose up` *you will use the service's name*.
  {% endhint %}

{% hint style="info" %}
When communicating between services (containers), note that you must use the `CONTAINER_PORT` and not the `HOST_PORT`.
{% endhint %}

{% hint style="danger" %}
Avoid referencing containers by `IP`, since their `IP`s will change over time when re-created.
{% endhint %}

#### Configuring the Default network

```yaml
services:
  # ...
  
networks:
  default:
    name: custom_name
    driver: host
```

#### Aliases with Links&#x20;

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

```yaml
services:
  app:
    links:
      - "db:database"
  db:
    image: postgres
```

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.

```yaml
services:
  angular:
    build: ./angular.dockerfile
    network:
      - frontend
  node:
    build: ./node.dockerfile
    networks:
      - frontend
      - backend
  db:
    build: postgres
    networks:
      - backend
      
networks:
  frontend:
    name: angular_network
    driver: bridge
  # Just specifing the name is enough to create it
  backend: {}
```

#### Joining External Networks

```yaml
services:
  # ...
  
networks:
  network1:
    # Compose will look for a network with this name
    name: the-name-of-the-existing-network
    external: true
```

## Compose CLI

The `docker compose` has a [couple of flags](https://docs.docker.com/reference/cli/docker/compose/) that can be used.

<table><thead><tr><th width="247">Flag</th><th>Description</th></tr></thead><tbody><tr><td><code>--dry-run</code></td><td>Execute commands in dry run mode.</td></tr><tr><td><code>--env-file</code></td><td>Specify an alternate environment file.</td></tr><tr><td><code>-f</code> or <code>--file</code></td><td>Compose configuration files.</td></tr><tr><td><code>--progress</code></td><td>Set thype of progress output. (auto, tty, plain, json, quiet)</td></tr><tr><td><code>--project-directory</code></td><td>Specify an alternate working directory. (default: the path of the, first specified, Compose file)</td></tr><tr><td><code>-p</code> or <code>--project-name</code></td><td>Project name. (<code>/^[a-z0-9]+[a-z0-9\-\_]*/</code>)</td></tr></tbody></table>

### [`down`](https://docs.docker.com/reference/cli/docker/compose/down/)

`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.

<table><thead><tr><th width="247">Flag</th><th>Description</th></tr></thead><tbody><tr><td><code>--remove-orphans</code></td><td>Remove containers for services not defined in the Compose file.</td></tr><tr><td><code>--rmi</code></td><td>Removes Images used by services. ("local" remove only images that don't have a custom tag <code>("local" | "all")</code>)</td></tr><tr><td><code>-t</code> or <code>--timout</code></td><td>Specify a shutdown timout in seconds.</td></tr><tr><td><code>-v</code> or <code>--volumes</code></td><td><ul><li>Removes named volumes declared in the <code>volumes</code> section of the Compose file.</li><li>Removes anonymous volumes attached to containers.</li></ul></td></tr></tbody></table>

### [`logs`](https://docs.docker.com/reference/cli/docker/compose/logs/)

`docker compose logs [OPTIONS] [SERVICES]`

Display log outputs from services.

### [`ps`](https://docs.docker.com/reference/cli/docker/compose/ps/)

`docker compose ps [OPTIONS] [SERVICE]`

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

By default, only running containers are shown.

<table><thead><tr><th width="247">Flag</th><th>Description</th></tr></thead><tbody><tr><td><code>-a</code> or <code>--all</code></td><td>Show all containers. (Including the ones created without Compose)</td></tr><tr><td><code>--format</code></td><td>Format output with custom template. (table, json, TEMPLATE)</td></tr><tr><td><code>--orphans</code></td><td>Include services not declared by project.</td></tr></tbody></table>

### [`run`](https://docs.docker.com/reference/cli/docker/compose/run/)

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

Runs a one-time command against a service.

### [`up`](https://docs.docker.com/reference/cli/docker/compose/up/)

`docker compose up [OPTIONS] [SERVICES]`

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

{% hint style="info" %}
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.
{% endhint %}

{% hint style="warning" %}
An exit code `1` is generated if the process encounter an error.

If the process was interrupted using `SIGINT` (Ctrl + C) or `SIGTERM`, the containters are stopped, and the exit code is `0`.
{% endhint %}

<table><thead><tr><th width="326">Flag</th><th>Description</th></tr></thead><tbody><tr><td><code>--abort-on-container-exit</code></td><td>Stop all containers if any container was stopped. (Incompatible with <code>-d</code>)</td></tr><tr><td><code>--abort-on-container-failure</code></td><td>Stop all container if any container exited with failure. (Incompatible with <code>-d</code>)</td></tr><tr><td><code>--build</code></td><td>Build Images before starting containers.</td></tr><tr><td><code>-d</code> or <code>--detach</code></td><td>Run containers in the background.</td></tr><tr><td><code>--force-recreate</code></td><td>Recreate containers even if their configuration and Image haven't changed.</td></tr><tr><td><code>--no-attach</code></td><td>Do not attach (stream logs) to specified services.</td></tr><tr><td><code>--no-deps</code></td><td>Do not recreate services linked services.<br><em>Ex.: If you change a service config, and don't need to rebuild the dependent services.</em></td></tr><tr><td><code>--no-recreate</code></td><td>Don't recreate containers even if their configuration and Image have changed.</td></tr><tr><td><code>--no-start</code></td><td>Don't start the services after creating them.</td></tr><tr><td><code>--quiet-pull</code></td><td>Pull images without printing progress information.</td></tr><tr><td><code>-V</code> or <code>--renew-anon-volumes</code></td><td>Recreate anonymous volumes instead of retrieving data from the previous containers.</td></tr><tr><td><code>--timestamps</code></td><td>Show timestamps.</td></tr><tr><td><code>--wait</code></td><td>Wait for services to be running|healthy. (Implies detached mode)</td></tr><tr><td><code>--wait-timeout</code></td><td>Maximum duration to wait for project to be running|healthy.</td></tr></tbody></table>

**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**

```yaml
services:
  composer:
    build:
      # The name of the file
      dockerfile: ./dockerfiles/composer.dockerfile
```

**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.

```yaml
services:
  backend:
    ...
  frontend:
    ...
    depends_on:
      - backend
```

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

```bash
docker-compose up --build
```

**Front end Containers**

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

```yaml
services:
  frontend:
    ...
    stdin_open: true
    tty: true
```

## YAML Tips & Tricks

Some YAML tips when creating the Compose files.

### [Fragments (Anchors and Aliases)](https://docs.docker.com/reference/compose-file/fragments/)

{% hint style="danger" %}
When using `anchors`, use **Map Syntax** when providing `<key>` and `<values>`. **Array Syntax** only allows `<key>`.
{% endhint %}

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

```yaml
services:
  first:
    image: my-image:latest
    environment: &env
      # Array syntax can ONLY be used if no values are passed
      - CONFIG_KEY
      - EXAMPLE_KEY
      - DEMO_VAR
  second:
    image: another-image:latest
    environment: *env
```

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

```yaml
services:
  first:
    image: my-image:latest
    environment: &env
      # Use Map syntax when providing values along
      CONFIG_KEY: 1h12j4
      EXAMPLE_KEY:
      DEMO_VAR: "false"
  second:
    environment:
      <<: *env
      ADDITIONAL_VAR: value
```

#### Pulling more than one anchor

```yaml
# Using Extensions
x-env1: &env-1
  VAR1: value1
  VAR2: value2
x-env2: &env-2
  VAR3: value3

services:
  app:
    environment: [*env-1, *env-2]
```

### [`Extensions`](https://docs.docker.com/reference/compose-file/extension/)

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`.&#x20;

```yaml
x-network-config: &net-conf
  bnetwork:
    driver: host
    name: the-b-network
      
services:
  app:
    networks: *net-conf
```

### [`Interpolation`](https://docs.docker.com/reference/compose-file/interpolation/)

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

Both `$VARIABLE` and `${VARIABLE}` are supported.

{% hint style="danger" %}
Interpolation is mostly for `<values>`, the only properties that allows you to interpolate on `<keys>` are `labels` and `environment`.
{% endhint %}

## Compose Properties

{% embed url="<https://docs.docker.com/reference/compose-file/>" %}

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

### [`name`](https://docs.docker.com/reference/compose-file/version-and-name/)

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.

```yaml
name: project-name
```

### [`service`](https://docs.docker.com/reference/compose-file/services/) (required)

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

{% hint style="info" %}
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`.
{% endhint %}

{% hint style="info" %}
Specify durations like `{value}{unit}`, `{unit}` may be:

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

Ex.: `40s`, `1m30s`, `1h30m50s20ms`.
{% endhint %}

Some [attributes](https://docs.docker.com/reference/compose-file/services/#attributes) a service may declare:

<table><thead><tr><th width="214">Property</th><th width="125">Type</th><th>Description</th></tr></thead><tbody><tr><td><a href="https://docs.docker.com/reference/compose-file/build/"><code>build</code></a></td><td><em>value</em></td><td>Defines how to create the Docker image for the service.<br><em>(Usually the path to the Dockerfile)</em></td></tr><tr><td><code>blkio_config</code></td><td><em>map</em></td><td>Defines a set of configurations to set IO block limits.</td></tr><tr><td><code>cap_add</code></td><td><em>array</em></td><td>Additional container <a href="https://man7.org/linux/man-pages/man7/capabilities.7.html">capabilities</a>.</td></tr><tr><td><code>command</code></td><td><em>value</em></td><td>Overrides the default command declared by the container image.<br><em>(Ex.: By Dockerfile's</em> <code>CMD</code><em>)</em><br><em>(If value is</em> <code>''</code> <em>or</em> <code>[]</code><em>, default command is overwriten to be empty)</em></td></tr><tr><td><code>container_name</code></td><td><em>value</em></td><td>For custom container's name.<br><em>(If defined, may stop Compose from scaling beyond one container</em>)</td></tr><tr><td><code>cpu_count</code></td><td><em>value</em></td><td>Defines the number of usable CPUs.</td></tr><tr><td><code>cpu_shares</code></td><td><em>value</em></td><td>As integer value, defines relative CPU weight versus other containers.</td></tr><tr><td><a href="https://docs.docker.com/reference/compose-file/services/#depends_on"><code>depends_on</code></a></td><td><em>array or map</em></td><td>To define dependency to other services.<br>Will also control the order of startup and shutdown.</td></tr><tr><td><a href="https://docs.docker.com/reference/compose-file/deploy/"><code>deploy</code></a></td><td><em>map</em></td><td>Set of deployment specifications for managing the behavior of containers across different environments.</td></tr><tr><td><code>domainname</code></td><td><em>value</em></td><td>Custom domain name for the container.</td></tr><tr><td><code>entrypoint</code></td><td><em>value or array</em></td><td>Overrides the default <code>entrypoint</code> declared by the container image.<br><em>(Ex.: By Dockerfile's</em> <code>ENTRYPOINT</code><em>)</em><br><em>(If value is</em> <code>''</code> <em>or</em> <code>[]</code><em>, default command is overwriten to be empty)</em></td></tr><tr><td><a href="https://docs.docker.com/reference/compose-file/services/#env_file"><code>env_file</code></a></td><td><em>value, array or map</em></td><td>Specify one or more files that contain <code>env</code> variables.</td></tr><tr><td><a href="https://docs.docker.com/reference/compose-file/services/#environment"><code>environment</code></a></td><td><em>array or map</em></td><td>To list <code>env</code> variables.</td></tr><tr><td><a href="https://docs.docker.com/reference/compose-file/services/#extends"><code>extends</code></a></td><td><em>map</em></td><td>Share common configurations among services.</td></tr><tr><td><code>extra_hosts</code></td><td><em>array or map</em></td><td>Adds hostname mappings to container's network interface configuration.<br><em>Ex.: (</em><code>/etc/hosts</code><em>)</em></td></tr><tr><td><a href="https://docs.docker.com/reference/compose-file/services/#healthcheck"><code>healthcheck</code></a></td><td><em>map</em></td><td>Declares a check to determine if the service containers are "healthy".</td></tr><tr><td><code>hostname</code></td><td><em>value</em></td><td>Custom hostname for the container.</td></tr><tr><td><code>image</code></td><td><em>value</em></td><td>Another way to define which image to use.<br><em>(Like if you don't have a Dockerfile)</em></td></tr><tr><td><a href="https://docs.docker.com/reference/compose-file/services/#links"><code>links</code></a></td><td><em>array</em></td><td>Network link aliases to services in another container.<br><em>(Ex.:</em> <code>SERVICE:ALIAS</code><em>)</em></td></tr><tr><td><code>mem_limit</code></td><td><em>value</em></td><td><p>Limit the amount of memory a container can allocate.</p><p><em>Ex.: (300m, 1gb)</em><br><em>(Must be consistent with</em> <code>limits.memory</code> <em>attribute in</em> <code>deploy</code> <em>attribute</em>)</p></td></tr><tr><td><code>mem_reservation</code></td><td><em>value</em></td><td><p>Reserves an amount of memory a container can allocate.</p><p><em>Ex.: (300m, 1gb)</em><br><em>(Must be consistent with</em> <code>reservations.memory</code> <em>attribute in</em> <code>deploy</code> <em>attribute</em>)</p></td></tr><tr><td><a href="https://docs.docker.com/reference/compose-file/services/#network_mode"><code>network_mode</code></a></td><td><em>value</em></td><td>Sets the container network mode.<br>(<code>none</code>, <code>host</code>, <code>service:{name}</code>, <code>container:{name}</code>)</td></tr><tr><td><a href="https://docs.docker.com/reference/compose-file/services/#networks"><code>networks</code></a></td><td><em>array or map</em></td><td>Defines the networks the service is attached to.</td></tr><tr><td><a href="https://docs.docker.com/reference/compose-file/services/#networks"><code>ports</code></a></td><td><em>value</em> or <em>array</em></td><td>Define port mapping between host and container  (<code>host:container</code>).</td></tr><tr><td><code>privileged</code></td><td><em>value</em></td><td>Configures the service to run with elevated priviledges.</td></tr><tr><td><a href="#service-profiles"><code>profiles</code></a></td><td><em>array or map</em></td><td>Defines the list of named profiles for the service to be under.</td></tr><tr><td><a href="https://docs.docker.com/reference/compose-file/services/#restart"><code>restart</code></a></td><td><em>value</em></td><td>Defines the restart policy on container termination.</td></tr><tr><td><a href="https://docs.docker.com/reference/compose-file/services/#secrets"><code>secrets</code></a></td><td><em>array</em></td><td>List of variables for sensitive data. Reference top-evel secrets or create local ones.</td></tr><tr><td><code>tty</code></td><td><em>value</em></td><td>Configure the service to run with <code>tty</code>.<br><em>(Same as running the container with</em> <code>-t</code> <em>flag.</em></td></tr><tr><td><code>user</code></td><td><em>value</em></td><td>Overrides the user to run the container process.<br><em>(This overwrites the</em> <code>user</code> <em>defined in Dockerfile)</em></td></tr><tr><td><a href="https://docs.docker.com/reference/compose-file/services/#volumes"><code>volumes</code></a></td><td><em>array</em></td><td>Define mount host paths or named volumes assessible by the containers.<br><em>(For the volume to be reused by multiple services, it must also be declared as top-level)</em></td></tr><tr><td>working_dir</td><td>value</td><td>Overrides the container's working directory.<br><em>(This overrides</em> <code>WORKDIR</code> <em>from Dockerfile)</em></td></tr></tbody></table>

### [`networks`](https://docs.docker.com/reference/compose-file/networks/)

Check more info over Network [up here](#network).

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

Some [attributes](https://docs.docker.com/reference/compose-file/networks/#attributes) a service may declare:

<table><thead><tr><th width="215">Property</th><th width="127">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>driver</code></td><td><em>value</em></td><td>Specifies the network driver to use.</td></tr><tr><td><code>external</code></td><td><em>value</em></td><td>Specifies if the network is maintained outside the application.</td></tr><tr><td><a href="https://docs.docker.com/reference/compose-file/networks/#ipam"><code>ipam</code></a></td><td><em>map</em></td><td>To configure more in-depth options for the network.</td></tr><tr><td><code>name</code></td><td><em>value</em></td><td>Custom name for the network.</td></tr></tbody></table>

### [`volumes`](https://docs.docker.com/reference/compose-file/volumes/)

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

Some [attributes](https://docs.docker.com/reference/compose-file/volumes/#attributes) a service may declare:

<table><thead><tr><th width="215">Property</th><th width="127">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>driver</code></td><td><em>value</em></td><td>Specifies the volume driver to use.</td></tr><tr><td><code>external</code></td><td><em>value</em></td><td>Specifies if the volume is maintained outside the application.</td></tr><tr><td><code>name</code></td><td><em>value</em></td><td>Custom name for the volume.</td></tr></tbody></table>

### [`configs`](https://docs.docker.com/reference/compose-file/configs/)

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

Check more info on the docs.

### [`secrets`](https://docs.docker.com/reference/compose-file/secrets/)

Check more info over Secrets [up here](#secrets).

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`.
