Edit:
You can escape the environment variable (double dollar symbol $$ instead of one $) in docker-compose.yml to prevent it from being replaced in the command of the container. However, since the replacement should be done at runtime, a shell (command) has to be run in the container to do the replacement, e.g.
version: '3.7'
services:
tmp:
image: alpine
environment:
FOO: foo
command: sh -c 'echo "$${FOO:-foobar}"'
Old answer:
I just figured out that nested environment variables are not replaced.
version: '3.7'
services:
tmp:
image: alpine
environment:
FOO: foo
command: sh -c 'echo FOO is "${FOO_OVERWRITE:-${FOO:-foobar}}" && env'
If you run
docker-compose -p app up
you get
# echo output
FOO is foo
# env output
FOO=foo
You get the same result, even if you run
FOO=ignored docker-compose -p app up
However, if you run
FOO_OVERWRITE=overwritten docker-compose -p app up
you get
# echo output
FOO is overwritten}
# env output
FOO=foo
The overwrite does not work probably, since } is part of the output. Considering this, you should not use this solution ;)
Note: You do not get } if you run the same command in a shell (no Docker involved):
$ sh -c 'echo FOO is "${FOO_OVERWRITE:-${FOO:-foobar}}"'
FOO is foobar
If the environment variable is not defined in the container, i.e. remove
environment:
FOO: foo
from docker-compose.yml, i.e.
version: '3.7'
services:
tmp:
image: alpine
command: sh -c 'echo FOO is "${FOO_OVERWRITE:-${FOO:-foobar}}" && env'
you get the default defined in the command
# echo output
FOO is foobar
# env output does not contain FOO
Docker Compose version 1.26.0