How to bind mount a local folder into several services in docker-compose, without having to repeat each time?

942 views Asked by At

I have a docker-compose.yml file where I'm defining several services, each resulting in an individual container. In short it looks like this:

version: "3.9"
services:
    dev_1:
        build:
            context: .
            dockerfile: ./Dockerfile
            target: dev_1

        volumes:
            -   type: bind
                source: /home/foo
                target: /home/bar

    dev_2:
        build:
            context: .
            dockerfile: ./Dockerfile
            target: dev_2

        volumes:
            -   type: bind
                source: /home/foo
                target: /home/bar

You can see that for each service I have to bind mount the volume again, by copying the same lines of code. But in my application I have several such folders which I want to mount into all the services, but without having to copy all the lines again and again.

Is there a way to shorten this, e.g. by using the volumes directive?

So far I only found suggestions to use a shared volume, but this is not practical for me, as such a volume copies the data into the volume. But I have plenty of data (Terrabytes) which I don't want to copy. I just want to bind mount it.

The docker compose version doesn't matter - right now I'm using 3.9. As long as it works everything is allowed.

Thanks in advance!

1

There are 1 answers

3
burn4science On BEST ANSWER

I found an answer on medium, that solves my problem: using anchors, aliases and the x-flag makes it possible to define the volumes in a central service, which can then be reused in the other services:

version: "3.9"

x-volumes_all: &volumes_all
    volumes:
        - &vol1 /home/foo1:/home/bar1
        - &vol2 /home/foo2:/home/bar2

services:
    <<: *volumes_all
    dev_1:
        build:
            context: .
            dockerfile: ./Dockerfile
            target: dev_1

        volumes:
            -   *vol1

    dev_2:
        build:
            context: .
            dockerfile: ./Dockerfile
            target: dev_2

        volumes:
            -   *vol2

At first, I define x-volumes_all as the common service - the preceding x- indicates that the service is hidden and only there to be reused in other services. Additionally, I use the anchor & to give it an arbitrary name (&volumes_all). In the volumes section I simply define my bind mounts, again using anchors to give each volume a name (&vol1 and &vol2).

Later, in my service section I import the hidden service (<<: *volumes_all) by dereferencing the alias using *. In the same way I can now include the individual volumes, called again by * and their respective name.

That way I reduce errors as I only need to define everything once.

Found here: Don’t Repeat Yourself with Anchors, Aliases and Extensions in Docker Compose Files

Thanks folks!