Share Compose configurations between files and projects
From the end of June 2023 Compose V1 won’t be supported anymore and will be removed from all Docker Desktop versions.
Make sure you switch to Compose V2 with the
docker composeCLI plugin or by activating the Use Docker Compose V2 setting in Docker Desktop. For more information, see the Evolution of Compose
Compose supports two methods of sharing common configuration:
- Extend an entire Compose file by using multiple Compose files
- Extend individual services with the
Multiple Compose files
Using multiple Compose files lets you to customize a Compose application for different environments or different workflows.
Understanding multiple Compose files
By default, Compose reads two files, a
docker-compose.yml and an optional
docker-compose.override.yml file. By convention, the
contains your base configuration. The override file, as its name implies, can
contain configuration overrides for existing services or entirely new
If a service is defined in both files, Compose merges the configurations using the rules described in Adding and overriding configuration.
To use multiple override files, or an override file with a different name, you
can use the
-f option to specify the list of files. Compose merges files in
the order they’re specified on the command line. See the
docker compose command reference for more information
When you use multiple configuration files, you must make sure all paths in the
files are relative to the base Compose file (the first Compose file specified
-f). This is required because override files need not be valid
Compose files. Override files can contain small fragments of configuration.
Tracking which fragment of a service is relative to which path is difficult and
confusing, so to keep paths easier to understand, all paths must be defined
relative to the base file.
Example use case
In this section, there are two common use cases for multiple Compose files: changing a Compose app for different environments, and running administrative tasks against a Compose app.
A common use case for multiple files is changing a development Compose app for a production-like environment (which may be production, staging or CI). To support these differences, you can split your Compose configuration into a few different files:
Start with a base file that defines the canonical configuration for the services.
web: image: example/my_web_app:latest depends_on: - db - cache db: image: postgres:latest cache: image: redis:latest
In this example the development configuration exposes some ports to the host, mounts our code as a volume, and builds the web image.
web: build: . volumes: - '.:/code' ports: - 8883:80 environment: DEBUG: 'true' db: command: '-d' ports: - 5432:5432 cache: ports: - 6379:6379
When you run
docker compose up it reads the overrides automatically.
Now, it would be nice to use this Compose app in a production environment. So, create another override file (which might be stored in a different git repo or managed by a different team).
web: ports: - 80:80 environment: PRODUCTION: 'true' cache: environment: TTL: '500'
To deploy with this production Compose file you can run
$ docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
This deploys all three services using the configuration in
docker-compose.prod.yml (but not the
dev configuration in
See production for more information about Compose in production.
Another common use case is running when necessary or administrative tasks against one or more services in a Compose app. This example demonstrates running a database backup.
Start with a docker-compose.yml.
web: image: example/my_web_app:latest depends_on: - db db: image: postgres:latest
In a docker-compose.admin.yml add a new service to run the database export or backup.
dbadmin: build: database_admin/ depends_on: - db
To start a normal environment run
docker compose up -d. To run a database
backup, include the
docker-compose.admin.yml as well.
$ docker compose -f docker-compose.yml -f docker-compose.admin.yml \ run dbadmin db-backup
extends keyword enables the sharing of common configurations
among different files, or even different projects entirely. Extending services
is useful if you have several services that reuse a common set of configuration
extends you can define a common set of service options in one
place and refer to it from anywhere.
Keep in mind that
depends_on are never shared between
extends. These exceptions exist to avoid implicit
dependencies; you always define
volumes_from locally. This ensures
dependencies between services are clearly visible when reading the current file.
Defining these locally also ensures that changes to the referenced file don’t
Understand the extends configuration
When defining any service in
docker-compose.yml, you can declare that you are
extending another service like this:
services: web: extends: file: common-services.yml service: webapp
This instructs Compose to re-use the configuration for the
defined in the
common-services.yml file. Suppose that
looks like this:
services: webapp: build: . ports: - "8000:8000" volumes: - "/data"
In this case, you get exactly the same result as if you wrote
docker-compose.yml with the same
values defined directly under
You can go further and define (or re-define) configuration locally in
services: web: extends: file: common-services.yml service: webapp environment: - DEBUG=1 cpu_shares: 5 important_web: extends: web cpu_shares: 10
You can also write other services and link your
web service to them:
services: web: extends: file: common-services.yml service: webapp environment: - DEBUG=1 cpu_shares: 5 depends_on: - db db: image: postgres
Example use case
Extending an individual service is useful when you have multiple services that have a common configuration. The example below is a Compose app with two services: a web application and a queue worker. Both services use the same codebase and share many configuration options.
In a common.yml we define the common configuration:
services: app: build: . environment: CONFIG_FILE_PATH: /code/config API_KEY: xxxyyy cpu_shares: 5
In a docker-compose.yml we define the concrete services which use the common configuration:
services: webapp: extends: file: common.yml service: app command: /code/run_web_app ports: - 8080:8080 depends_on: - queue - db queue_worker: extends: file: common.yml service: app command: /code/run_worker depends_on: - queue
Adding and overriding configuration
Compose copies configurations from the original service over to the local one. If a configuration option is defined in both the original service and the local service, the local value replaces or extends the original value.
For single-value options like
mem_limit, the new value
replaces the old value.
services: myservice: # ... command: python app.py
services: myservice: # ... command: python otherapp.py
services: myservice: # ... command: python otherapp.py
For the multi-value options
tmpfs, Compose concatenates both sets of values:
services: myservice: # ... expose: - "3000"
services: myservice: # ... expose: - "4000" - "5000"
services: myservice: # ... expose: - "3000" - "4000" - "5000"
In the case of
“merges” entries together with locally-defined values taking precedence. For
labels, the environment variable or label name determines
which value is used:
services: myservice: # ... environment: - FOO=original - BAR=original
services: myservice: # ... environment: - BAR=local - BAZ=local
services: myservice: # ... environment: - FOO=original - BAR=local - BAZ=local
devices are merged using the mount path in the
services: myservice: # ... volumes: - ./original:/foo - ./original:/bar
services: myservice: # ... volumes: - ./local:/bar - ./local:/baz
services: myservice: # ... volumes: - ./original:/foo - ./local:/bar - ./local:/baz