I have the following broken docker-compose file
version: '3.4'
x-vols1: &vols-1
- /home/:/home/
x-vols2: &vols-2
- /tmp/:/tmp/
services:
app1:
container_name: app1
image: app1
volumes:
<<: *vols-1
app2:
container_name: app2
image: app2
volumes:
<<: *vols-1
<<: *vols-2
This fails with the following error
$ docker-compose -f test.yaml config
ERROR: yaml.constructor.ConstructorError: while constructing a mapping
in "./test.yaml", line 14, column 13
expected a mapping for merging, but found scalar
in "./test.yaml", line 4, column 7
Question 1: How can I merge arrays in docker-compose
? The syntax that I am trying to use is the one for merging dicts
Question 2: If there is no way to merge arrays, is there a workaround?
Use case: I have multiple services, some of them map some volumes, others map other volumes, others map all volumes. I would like to not repeat myself.
Thank you!
Docker Tip #82: Using YAML Anchors and X Properties in Docker Compose YAML anchors let you reuse parts of your YAML file like functions. You can use them to share default settings between services. This is quite handy when you want to DRY out some bits of your docker-compose.yml file.
Anchors need to be before aliasing (e.g. in an aliasor merge key), can remain unused and can be re-defined, last one wins at the time of use (flow is from top to bottom). Example-YAMLwith Aliases, Referencesand Merge Keystaken from the Merge Keyworking draft:
It’s very handy for setting up common things like logging or various other Docker properties. You can name the x- properties anything you want as long as it’s valid YAML syntax. These x- properties are called “Extension fields” in Docker Compose’s documentation. The basic idea is the extension field just acts as a “place” to define the YAML anchor.
But, it can be easy to end up with repeated blocks in stacks with lots of similar services or configurations. Don’t Repeat Yourself (DRY) by leveraging YAML aliases and anchors, and the upcoming extension fields feature in the Docker Compose file format.
The Yaml merge syntax is for merging mappings, not for arrays. For more on that, see this issue. However, if you are just adding single volumes, you don't need to merge anything. Just insert the alias as an array entry:
version: '3.4'
x-vols1: &vols-1
"/home/:/home/"
x-vols2: &vols-2
"/tmp/:/tmp/"
services:
app1:
container_name: app1
image: app1
volumes:
- *vols-1
app2:
container_name: app2
image: app2
volumes:
- *vols-1
- *vols-2
The desired behavior can be achieved by using multiple docker-compose
files, one for each volume. Note that the anchors and aliases are not required, but keeping them in to align with the question.
base.yaml
version: '3.4'
services:
app1:
container_name: app1
image: app1
app2:
container_name: app2
image: app2
vol1.yaml
version: '3.4'
x-vols1: &vols-1
volumes:
- /home/:/home/
services:
app1:
container_name: app1
image: app1
<<: *vols-1
app2:
container_name: app2
image: app2
<<: *vols-1
vol2.yaml
version: '3.4'
x-vols2: &vols-2
volumes:
- /tmp/:/tmp/
services:
app2:
container_name: app2
image: app2
<<: *vols-2
Verify as
$ docker-compose -f base.yaml -f vol1.yaml -f vol2.yaml config
Result
services:
app1:
container_name: app1
image: app1
volumes:
- /home:/home:rw
app2:
container_name: app2
image: app2
volumes:
- /home:/home:rw
- /tmp:/tmp:rw
version: '3.4'
Additional documentation https://docs.docker.com/compose/extends/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With