How to make all volumes use local driver or specify custom name for volume in docker-compose.yml

version: '3.9'
services:
  mysql:
    # ...  
    volumes: # Persistent data
      - ${MYSQL_PERSISTENT_VOLUME}:/var/lib/mysql
volumes:
  ${MYSQL_PERSISTENT_VOLUME}:
    driver: local

We need to be able to set the driver for the volume (or all volumes) as local, and we need the volume name to be a variable set in .env. How can this be done? As written, we’re getting the following error:

volumes Additional property ${MYSQL_PERSISTENT_VOLUME} is not allowed

Not with docker compose alone. You would need your own template engine to generate a compose file that already generates the compose file you want to use. Here is a makefile example for how this could look like with envsubst: Data directory "/var/lib/postgresql/data" has wrong ownership... on Linux? - #10 by meyay.

Though, what’s wrong with having fixed names in your compose file? The project name for the deployment will be prefixed to the volume name on the host. You could use a fixed name like myvolume and deploy your compose project with docker compose --project-name a up -d and get the volume a_myvolume, then deploy the same compose file with another project name like docker compose --project-name b up -d and would get the volume name b_myvolume. Inside the compose file the reference would remain myvolume in both cases.

The motivation is beside the point, but it’s because we want to test multiple branches in our development environment and devs will need to switch out databases to match the versions linked to each branch until they are merged and migrations happen. Creating volumes named by the branch is a trivial way to accomplish this.

For anyone who needs this, you can accomplish it as follows:

version: '3.9'
services:
  mysql:
    # ...  
    volumes: # Persistent data
      - persistent_vol:/var/lib/mysql
volumes:
  persistent_vol:
    name: ${MYSQL_PERSISTENT_VOLUME:-default-volume-name}
    driver: local