Using Persistent Volumes With Docker Swarm

How to Create a Persistent
Application in Three Steps or Less

Now that we’ve covered how to Provision Persistent Volumes In One Easy Step, it’s time to put those volumes to use. Our software package features a Docker plugin that integrates our volumes seamlessly into the Docker experience.

This blog covers how to utilize the integration most effectively, and provides examples of persistent storage in container applications.

Explicit Volume Creation

As a refresher, Docker uses -v to mount a directory or volume to a container, and --mount to do the same for a Swarm service. This argument can take the names of a volume made by the CIO driver.

Creating a volume with Docker is the same as creating one with CIO, except you must specify the volume driver and the name:

docker volume create --driver cio \
--name postgres-data

Additionally, all other parameters from before, including capacity, labels, and profiles, must be passed in via the –opt or -o flag. Options are mapped 1:1; therefore, both -o capacity=25 and -o c=25 are valid. Note that the --iops and --bandwidth flag values are comma-delimited when creating through Docker!

See across for an example of both the mapping and the comma-delimited values in use:


docker volume create --driver cio \ 
--name postgres-data --opt c=25 \ 
-o iops=100,1000

It should be noted that while you CAN use the –node flag, it’s not necessary as the CIO Orchestration system will automatically move the volume to where it is needed.

Now that we have a volume, we can use it with Docker. Here’s an example of using the Storidge volume as the basis for a persistent container:

docker run --name postgres \
-e POSTGRES_PASSWORD=mysecretpassword \
-v postgres-data:/var/lib/postgresql/data -d postgres

The result is an easy, persistent database!

Implicit Volumes

Implicit creation cuts out the first step of volume creation. It occurs when a docker service or docker run command is fed the name of a volume that does not yet exist, and docker is forced to automatically create the named volume to continue. Note that this requires the --volume-driver flag! Otherwise, a local (default) volume will be made.

docker run --name postgres \ 
-e POSTGRES_PASSWORD=mysecretpassword \ 
--volume-driver cio \
-v postgres-data:/var/lib/postgresql/data -d postgres

This results in the automatic creation of a default CIO volume. For docker run commands, there is currently no way to customize the volume implicitly.

Data volumes can also be created implicitly with the docker service create command. Unlike the docker run command, docker service create also allows storage to be provisioned with CIO’s volume options. This is accomplished through the --mount flag, but with different syntax:

docker service create \
--mount source=mysqldb,target=/var/lib/mysql,volume-driver=cio,\
volume-opt=capacity=300,volume-opt=profile=MYSQL \
--replicas 1 \
--name mysql \

Source refers to the name of a (yet unprovisioned) docker volume, and target refers to the mount point within the container. It is worth noting that in the case of a conflict between argument and profile exists (here, the capacity), CIO will prioritize the argument provided.

As can be seen, the provisioning and usage of persistent storage is quick and easy!

Thanks for Reading!

Did this article give you any ideas about persistent storage and Docker? Let us know on Twitter!

Or, leave a comment in the footer below.