dockerdocker-compose

Docker compose fails when trying to use external named volume


I’m trying to use an external named volume in my docker-compose.yml, but I keep getting an error about a non-existent bind source path.

I’ve already created the volume and verified it exists via docker volume inspect.

However, when I run docker compose up, I get this error:

Error response from daemon: invalid mount config for type "bind": bind source path does not exist: /home/myhomefolder/myrepo/db-data

Steps to Reproduce

  1. Create the volume:

    docker volume create db-data

    This is confirmed to exist:

    docker volume inspect db-data [
        {
            "Name": "db-data",
            "Driver": "local",
            "Mountpoint": "/var/lib/docker/volumes/db-data/_data",
            ...
        }
    ]
    
  2. Use the volume in docker-compose.yml:

    version: '3' 
    services:
      mongo:
        image: mongo:4.4.18
        restart: unless-stopped
        volumes:
          - source: db-data
            target: /data/db
            type: bind  # <-- suspect
            bind:
              create_host_path: false
          # - db-data:/data/db
          #   (When I try this uncommented, Docker creates a new anonymous volume, which is not what I want)
    
    volumes:
      db-data:
        external: true
    
  3. Run Docker Compose:

    docker compose up -d mongo

Produces:

Error response from daemon: invalid mount config for type "bind": bind
 source path does not exist: /home/myhomefolder/myrepo/db-data

docker compose tries to treat db-data as a host bind mount path, rather than a named volume. As a result, it complains that /home/myhomefolder/myrepo/db-data does not exist.

Additional Details


Solution

  • It seems like you’re mixing up named volumes with bind mounts.

    You're using:

    type: bind
    source: db-data
    target: /data/db
    

    But when you specify type: bind docker compose uses the "source" as host path on the filesystem (i.e., source: db-data → /home/…/myrepo/db-data).

    Since the directory doesn't exist (on the host) - you get:

    bind source path does not exist: /home/myhomefolder/myrepo/db-data

    a) Either use a named Volume

    Managed by Docker (in /var/lib/docker/volumes/...).

    If you already ran:

    docker volume create db-data
    

    You'd have a named volume called db-data. To use that volume as an external in Docker Compose, don't use type: bind

    Instead do:

    version: '3.9'
    services:
      mongo:
        image: mongo:4.4.18
        restart: unless-stopped
        volumes:
          - db-data:/data/db  
    volumes:
      db-data:
        external: true
    

    db-data:/data/db tells docker compose to use named volume db-data (instead of creating a new one).

    external: true tells compose “Don’t create this volume - it already exists.”

    So it will attach the existing named volume db-data to /data/db in your container.

    This is what you want if you want docker to manage data storage.

    b) or use a bind mount (mapping a host directory into a container)

    If you want mongo to store its data in a host directory (e.g. /home/myhomefolder/myrepo/db-data on your system), you must give compose a path on the host.

    e.g.:

    version: '3.9'
    services:
      mongo:
        image: mongo:4.4.18
        restart: unless-stopped
        volumes:
          - type: bind
            source: /home/myhomefolder/myrepo/db-data
            target: /data/db
    

    Ensure that the directory /home/myhomefolder/myrepo/db-data already exists on the host. Otherwise, docker will complain that it doesn't exist.

    (If you want docker to create the host path automatically, you can set bind.create_host_path: true in the compose spec, but be sure you are on a docker version that supports that.)


    FYI:

    If you do

    volumes:
      - db-data:/data/db
    

    without a volumes block referencing db-data: with external: true, compose will create a new named volume with the name <project>_db-data by default. That can look like random new volumes if you’re not expecting it.

    If you specify:

    volumes:
      db-data:
        external: true
    

    it will ensure that compose uses the volume named exactly db-data which you created yourself with docker volume create db-data.

    A named volume (backed by local driver) is not the same as a bind mount. They have different use-cases and must be declared differently in compose.

    Most of the time, if you want persistent data you'd use "docker named volumes" ( solution a) ), as it handles permissions, ownership, ...

    So your final docker-compose.yml might just be:

    version: '3.9'
    
    services:
      mongo:
        image: mongo:4.4.18
        restart: unless-stopped
        volumes:
          - db-data:/data/db
    
    volumes:
      db-data:
        external: true