Is it possible to use one shared named volume with multiple paths ?
I want to avoid repetition (DRY pattern) and avoid the creation of many named volumes for different paths that must be centralized due to business requirements (backup policies and so on).
I created the following named volume vol-web
based on NFS to share with many workers in my swarm cluster. But it can be reproduced locally. Just imagine that the volume points to a directory in your host.
docker volume create --driver local \
--opt type=nfs \
--opt o=addr=10.0.0.2,rw \
--opt device=:/var/web \
vol-web
The file below is only for test purposes, but I have many compose files, many services that will use this solution in the practice.
version: '3.8'
services:
database:
image: postgres:16.2
container_name: mydb
restart: always
environment:
- POSTGRES_USER=myuser
- POSTGRES_PASSWORD=mypassword
volumes:
- vol-web/pgdata:/var/lib/postgresql/data
- vol-web/config/pg/postgres-init.sh:/docker-entrypoint-initdb.d/postgres-init.sh
ports:
- "5432:5432"
nginx:
image: nginx:1.25.4
container_name: my-nginx
ports:
- "80:80"
- "443:443"
volumes:
- vol-web/config/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- vol-web/certbot/conf:/etc/letsencrypt
volumes:
vol-web:
I get actually the following error message:
service "database" refers to undefined volume vol-web/pgdata: invalid compose project
I am open for new solutions for this case.
Support for mounting volume subpaths is only available in Docker 26.0.0 (release March 20, 2024) and later (the pull request merged in janurary). This adds the subpath
option to volume mounts.
Using docker run
, we can mount the pgdata
subdirectory of the vol-web
volume on /data
like this:
docker run -it --rm \
--mount type=volume,source=vol-web,target=/data,volume-subpath=pgdata \
alpine sh
Support for this feature in docker compose
was only merged a few days ago and is only available in the compose
plugin version 2.26.0 and later; this doesn't appear to be available in a release of Docker at this time.
Prior to the above versions it was not possible to mount a volume subpath.
Unrelated to your question but important: when you create a volume like this:
docker volume create --driver local \
--opt type=nfs \
--opt o=addr=10.0.0.2,rw \
--opt device=:/var/web \
vol-web
And then use a volume entry like this in your compose file:
volumes:
vol-web:
They are not referring to the same volume. Volume, network, and container names in your compose file get prefixed by your compose project name (typically the name of the directory that contains the compose file, but can also be set explicitly). If you want your compose file to reference an existing external volume, you would need to set it as external
:
volumes:
vol-web:
external: true