Docker-compose prepends directory name to named volumes

Expectation

I would expect docker-compose-defined volumes to behave the same way as docker run-defined volumes.

Specifically, I would expect docker-compose-defined volumes to have the name I give them.

Actual Behavior

What actually happens is that the named volume gets prepended with (a simplified version of) the directory name from which the docker-compose command was run.

For instance, if I run from the deployment_root directory, and I name the volume my_named_vol, then I end up with a volume named deploymentroot_my_named_vol.

If this “is not a bug,” please explain the rationale.

Info & Steps to Reproduce

docker-compose-named-volume.yml:

version: '3'
services:

  solr:
    image: alpine:3.5
    container_name: foo
    volumes:
      - my_named_vol:/opt/foo
volumes:
  my_named_vol:

Result:

jjackson$ sw_vers && docker -v
ProductName:	Mac OS X
ProductVersion:	10.12.4
BuildVersion:	16E195
Docker version 17.03.1-ce, build c6d412e

jjackson$ docker-compose -f docker-compose-named-volume.yml up -d && \
>   echo "## named volume:" && \
>   docker volume ls | grep my_named_vol && \
>   echo "## stop" && \
>   docker-compose -f docker-compose-named-volume.yml down && \
>   echo "## rm volume" && \
>   docker volume rm $(docker volume ls | grep my_named_vol | awk '{print $2}')
Creating network "deploymentroot_default" with the default driver
Creating volume "deploymentroot_my_named_vol" with default driver
Creating foo
## named volume:
local               deploymentroot_my_named_vol
## stop
Removing foo ... done
Removing network deploymentroot_default
## rm volume
deploymentroot_my_named_vol

It’s not a bug.

docker-compose uses a project name. By default it’s the directory name which prevents collisions with existing containers.

But you can use -p to change the prefix name.

Okay, got it. Thanks.

You can use the external volume setting to avoid the prefix.

2 Likes

Now that I know these things about how it works, I’d like to know why it’s done this way.

If I specify a volume name, that’s the name I want it to have. I don’t want it to arbitrarily have a prefix (whether that’s the completely arbitrary seeming current directory, or whether it’s some contrived prefix I must give it–since -p "" doesn’t seem to work). @tnelis’s external suggestion is good to know about, but I do want docker-compose to set up my volumes.

So what’s the rationale for this project stuff? It seems presumptuous, but maybe I just haven’t stumbled on something that makes it all clear yet.

I personally find it rather useful on our QA boxes we use for CI for example, where we deploy many service compositions of the same codebase. Each uses a different project name so out-of-the-box the volumes never conflict. More generally it also makes them easier to recognize just like every other resource created by docker-compose (networks, containers, …). Not doing it this way would be quite inconsistent IMO.

@tnelis, are you explicit about the project names (-p), or do you have some kind of directory structure that informs the naming?

Depends on the situation, in most cases on development boxes the directory will be a good heuristic. When they aren’t we usually have small scripts we can source to set up the shell environment so we don’t have to type the -p option all the time.

In the case of the CI system I mentioned previously, we really do want to specify the project name explicitly since it will contain a high-entropy string to ensure the name doesn’t conflict. We do this with the COMPOSE_PROJECT_NAME environment variable which is more convenient for us in those procedures, though the semantics are exactly the same as the -p option.

It would be great to have full control, i.e. suppress the prefix completely. Currently this is possible with neither -p nor COMPOSE_PROJECT_NAME.

Rationale: I am converting a lot of deployments from scripts using docker run to compose.

Hi - I’m new to Docker, and would also like to use docker-compose to mount to an existing volume. It’s nice to know that the prefix can be specified via -p. However… where do I do this? on the docker-compose? In docker-compose.yml?

An example would be super helpful!

I believe this is what you need?

2 Likes