On April 7 Docker Inc. announced general availability of Docker Compose V1.2.0. Together with other bugfixes and features it added the new keyword extends
.
I thought that could be a good way to handle our needs to improve the configuration of our „application environments“ (e.g. dev, test, production). Because of some differences between them (mainly in handling of „data container“) we have to maintain several mostly identical Docker Compose configuration (aka „yaml“) files, one for each environment. Not nice …
Why the environments need to be different?
To shorten the round trip cycle time we map some container directories to local hard drives of our developer work stations (e.g. for html, css and javascript files), similar to this (simple) example based on „pure“ Docker taken from official Docker-NGINX-Image website [04]
docker run \ --name some-nginx \ -v /some/content:/usr/share/nginx/html:ro \ -d nginx
Of course, this isn’t a solution for production, there we use „data containers“ instead of mapped host directories.
As we found the differences and some spare time I updated my Docker environment (Mac OS X 10.10 with Docker V1.6.0, Docker-Machine V0.2.0 and Docker-Compose V1.2 ) to be able to try it out.
Part1: First Experiment
And of course I started first experiment without reading documentation completely. Therefore I run in some issues …
Given a Docker Compose configuration file „common.yml“
nexus: image: mapp/nexus:latest hostname: nexus user: root ports: - "8081:8081" volumes_from: - nexvol nexvol: image: busybox volumes: - /sonatype-work # Hint: # Setting user to root for service "nexus" is # necessary to get this example working, but is # meaningless for now and dealing with volumes # and rights would be a topic for another post ...
and another one named „extended.yml“
nexus: extends: file: common.yml service: nexus nexvol: extends: file: common.yml service: nexvol volumes: - /Users/bf/Projects/eval/nexus-home:/sonatype-work
Syntax itself focuses on services (not on files) and is imo easy to understand and well explained in [02].
Short summary:
Service „nexus“ defined in file „extended.yml“ (will refer to it as „extended::nexus“ from now) extends service „common::nexus“ without changing anything. But service „extended::nexvol“ extends service „common:nexvol“ by changing its volume definition to be mapped to a directory on my developer notebook.
Unfortunately, starting this service configuration lead me into trouble … 🙁
$ docker-compose -f extended.yml -p eval up -d Cannot extend service 'nexus' in /Users/bf/Projects/eval/common.yml: services with 'volumes_from' cannot be extended
What a pitty! Maybe it would be worth to spend some time studying documentation, which you can find at [03] (including explanation why this example doesn’t work), before starting to code something.
Part2: Get it working
Result from studying: „volumes_from“ and „links“ can’t be extended.
Only workaround I found is moving them from „parent“ to „child“ configuration, which means in our case from „common.yml“ to „extended.yml“
Finally „common.yml“ looks like
nexus: image: mapp/nexus:latest hostname: nexus user: root ports: - "8081:8081" nexvol: image: busybox volumes: - /sonatype-work
and „extended.yml“
nexus: extends: file: common.yml service: nexus volumes_from: - nexvol nexvol: extends: file: common.yml service: nexvol volumes: - /Users/bf/Projects/eval/nexus-home:/sonatype-work
Part3: Conclusion
The new keyword extends
is an improvement and makes working with Docker Compose more convenient, with some small disadvantages: I’m using „volumes_from“ and „links“ quiet often and they are still more or less duplicated between my environments.
Part4: References and links
[01] Docker Compose V1.2.0 Release Notes
[02] Docker Compose Documentation keyword „extends“
[03] Docker Compose – Tutorial and Reference for extending Services
[04] Official Docker image for NGINX