Different env-file but same yml with Docker Compose?
See Update #2 below. This is now possible!
This is a much requested feature of Docker Compose. Unfortunately, the answer at the moment is that you can't. I'd recommend subscribing to these GitHub issues to get a better idea when and if this feature gets implemented:
- https://github.com/docker/compose/issues/495
- https://github.com/docker/compose/pull/76
- https://github.com/docker/compose/pull/845
Issue #495 is actually the most commented in their issue repository at the moment. You are definitely not alone in wanting to do this.
Update:
The latest issue tracking is at https://github.com/docker/compose/issues/1377.
Update #2:
This functionality has been merged and is available as of Docker Compose 1.5.0. See https://github.com/docker/compose/blob/129092b7/docs/yml.md#variable-substitution for usage information.
It isn't a direct inclusion from the command line, but if you need a work-around before the #1765 merge (the fix for #1377) makes it into a release, you can use the extends
directive along with the env_file
directive. For convenience, the files from the simple examples below are reproduced in this repository.
Stupid simple example
base.yml
base:
image: busybox
command: bash -c 'echo "${WHO:-Simon} says, \"${SHOUTOUT:-Silence is golden.}\""'
one.env
WHO=Da Schwartz
SHOUTOUT=Get to...
one_glue.yml
one:
extends:
file: base.yml
service: base
env_file:
- one.env
two.env
WHO=Da Schwartz
SHOUTOUT=...da choppa!
two_glue.yml
two:
extends:
file: base.yml
service: base
env_file:
- two.env
Use
% for i in base one_glue two_glue ; do docker-compose --file "${i}.yml" up ; done
Recreating dockercomposeextendsenv_base_1...
Attaching to dockercomposeextendsenv_base_1
base_1 | Simon says, "Silence is golden."
dockercomposeextendsenv_base_1 exited with code 0
Gracefully stopping... (press Ctrl+C again to force)
Recreating dockercomposeextendsenv_one_1...
Attaching to dockercomposeextendsenv_one_1
one_1 | Da Schwartz says, "Get to..."
dockercomposeextendsenv_one_1 exited with code 0
Gracefully stopping... (press Ctrl+C again to force)
Recreating dockercomposeextendsenv_two_1...
Attaching to dockercomposeextendsenv_two_1
two_1 | Da Schwartz says, "...da choppa!"
dockercomposeextendsenv_two_1 exited with code 0
Gracefully stopping... (press Ctrl+C again to force)
Even simplerer example
The above works if you benefit from using .env
files. If you aren't so limited, you could keep the environment variable settings in the environment-specific "glue" .yml
files:
red_glue.yml
red:
extends:
file: base.yml
service: base
environment:
- WHO=Stallion
- SHOUTOUT=I am...
blue_glue.yml
blue:
extends:
file: base.yml
service: base
environment:
- WHO=Stallion
- SHOUTOUT=...the law!
Use
% for i in red_glue blue_glue ; do docker-compose --file "${i}.yml" up ; done
Creating dockercomposeextendsenv_red_1...
Attaching to dockercomposeextendsenv_red_1
red_1 | Stallion says, "I am..."
dockercomposeextendsenv_red_1 exited with code 0
Gracefully stopping... (press Ctrl+C again to force)
Creating dockercomposeextendsenv_blue_1...
Attaching to dockercomposeextendsenv_blue_1
blue_1 | Stallion says, "...the law!"
dockercomposeextendsenv_blue_1 exited with code 0
Gracefully stopping... (press Ctrl+C again to force)
A little more complicated
For what it's worth, the approach described in this answer allows for different .env
files on a per-instance basis, rather than per-invocation/environment. (I'm not sure how beneficial this is in practice, however.) In other words, you could do something like this:
testing.yml
# Only instance1 and instance2 are needed for testing
instance1:
extends:
file: base.yml
service: base
env_file:
- test.env # environment-specific
- instance1_test.env # instance-specific
instance2:
extends:
file: base.yml
service: base
env_file:
- test.env
- instance2_test.env
production.yml
# All four instances are used for production
instance1:
extends:
file: base.yml
service: base
env_file:
- prod.env # environment-specific
- instance1_prod.env # instance-specific
instance2:
extends:
file: base.yml
service: base
env_file:
- prod.env
- instance2_prod.env
instance3:
extends:
file: base.yml
service: base
env_file:
- prod.env
- instance3_prod.env
instance4:
extends:
file: base.yml
service: base
env_file:
- prod.env
- instance4_prod.env
You can start to see that extends
is pretty powerful, much more so than what the #1765 merge allows for.
Update Apr 2020
Docker Compose v3+ deprecated the
extends
feature.