One of the most needed feature to run a docker swarm is to manage volumes the most automatic way, so the orchestration is easier & cleaner.
Bind volumes are not a proper solution because it forces the swarm administrator to enable the same bind on every single node (or defining a label for bind enabled nodes and then restrict services by labels, not a clean solution neither).
Docker volume drivers
Docker supports more options than bind volumes or local volumes, one of the simpler drivers (at least because NFS is quite easy to be available and because docker deploys this driver in its core) is the NFS driver.
First of all an NFS share is needed, usually an IP address and a NFS share path, for instance IP 1.2.3.4
and share name /nfs/data-volume
.
Ensure NFS client is installed in every node (typically is installed), for instance for Ubuntu:
sudo apt-get install -y nfs-common
Then inside the docker-compose.yml
two things are required:
- First define a named volume at service as usual.
- Define a volume at
volumes
section usingnfs
volume type and passing the options to point to the NFS share.
Example
Let’s create a simple MariaDB service persisting data into a NFS volume, so it’s OK for the orchestrator to deploy the service in any of the nodes:
version: '3.7'
services:
mariadb:
image: mariadb:10.4.12
environment:
- MYSQL_USER=user
- MYSQL_PASSWORD=password
- MYSQL_ROOT_PASSWORD=password
- MYSQL_DATABASE=db
volumes:
- type: volume
source: mariadb_data
target: /var/lib/mysql
volumes:
mariadb_data:
driver_opts:
type: 'nfs'
o: 'addr=1.2.3.4,nolock,soft,rw'
device: ':/nfs/data-volume'
Troubleshooting
Several things could happen depending on your NFS configuration.
Permissions issues
It could happen that your NFS share is always accessible by an special user and any other user & group accessing it will generate invalid accesses. You can avoid this running the service with user ID and group ID of the NFS share.
...
services:
mariadb:
image: mariadb:10.4.12
user: 501:1000
...
Disable copying data from container to volume
By default when you create a volume into a path in which the container has data, this data will be copied into the volume, you can avoid that (maybe you have more permission errors) with the nodata
option.
...
services:
mariadb:
image: mariadb:10.4.12
...
volumes:
- type: volume
source: mariadb_data
target: /var/lib/mysql
volume:
nocopy: true
...