Volumes are the preferred method for persisting data for Docker containers. In this article, I will show how to create and use volumes for persistence, as well as tmpfs for temporary storage.
At its absolute simplest, creating and mounting a volume backed by a local directory looks like:
# make host directory mkdir -p /data # create docker volume from host directory sudo docker volume create --driver local --opt type=none --opt device=/data --opt o=bind --name=test # mount volume within container sudo docker run -it --mount source=test,target=/mymount alpine:latest /bin/df -h /mymount
Volume mounts
Now let’s look at a concrete example where we have a container running Apache2 delivering content from its web root. I’ve created a project on github called fabianlee/alpine-voltest and pushed it to docker hub.
This Dockerfile is small and just extends my alpine-apache image, and then takes it one step further by adding a volume at the directory where the web content is being served from the container.
FROM fabianlee/alpine-apache:2.4.41-r0 ... VOLUME "/var/www/localhost/htdocs/"
Let’s run the container as packaged, with no volumes mounted.
sudo docker run -d --rm --name alpine-voltest -p 8080:80 fabianlee/alpine-voltest:1.0.0
Opening the browser on the local Docker host to port 8080 yields.
The content returned is the default index.html placed onto the container in the “/var/www/localhost/htdocs” directory. Go ahead and stop the container now.
sudo docker stop alpine-voltest
But, if we mount a local volume to that container directory, we can control what it delivered from that web server.
# create local host content sudo mkdir -p /data/test echo "<h1>This is mounted on the docker host at /data/test/index.html</h1>" | sudo tee /data/test/index.html # create docker volume from host directory sudo docker volume create --driver local --opt type=none --opt device=/data/test --opt o=bind --name=test # volume details sudo docker volume inspect test # create container that uses test volume, mounts at web root sudo docker run -d --rm --name alpine-voltest -p 8080:80 --mount source=test,target=/var/www/localhost/htdocs fabianlee/alpine-voltest:1.0.0
And now the browser will return back the following content, what we placed into the local docker host file, “/data/test/index.html”.
Stop the container again.
sudo docker stop alpine-voltest # list volumes sudo docker volume ls
Even after the container is stopped these files are kept on the host, and future container instances can remount this volume.
Initial Volume population
If you start a container with a volume name that does not exist, then a new volume will be created. Additionally if the host directory is completely empty, the container’s content will populate (be copied to) the local host volume directory.
# start container, allow it to create volume and populate sudo docker run -d --rm --name alpine-voltest -p 8080:80 --mount source=newtest,target=/var/www/localhost/htdocs fabianlee/alpine-voltest:1.0.0 # volume details sudo docker inspect newtest | grep -i Mountpoint # get list of files in new volume (should now contain index.html) sudo ls -l /<dockerhome/volumes/newtest/_data # stop container sudo docker stop alpine-voltest # data still persists, but can be deleted sudo docker system prune sudo docker volume prune
Temporary filesystems
For small, ephemeral storage spaces that can only be used by a single container, there is the tmpfs filesystem. It is backed only by RAM storage on the host system.
Create 2Mb temporary disk space mounted at /tempdisk
$ sudo docker run -it --mount type=tmpfs,destination=/tempdisk,tmpfs-size=2m alpine:latest /bin/df -h /tempdisk Filesystem Size Used Available Use% Mounted on tmpfs 2.0M 0 2.0M 0% /tempdisk
Create 4Mb tmpfs space mounted at /tempdisk, then write file too large:
$ sudo docker run -it --mount type=tmpfs,destination=/tempdisk,tmpfs-mode=770,tmpfs-size=4m alpine:latest /usr/bin/fallocate -l 5M /tempdisk/my.test fallocate: fallocate '/tempdisk/my.test': No space left on device
REFERENCES
docker, container has access to all host resources
docker, storage types: bind, volume, tmpfs and use cases
digitalocean, volume to share data between container and host nginx
linuxhint, volume to share data between container and host, apache
stackoverflow, volume with opt type=none
devopsheaven, docker volumes opt type=non and nginx
mount man page, making same content accessible in two places (/olddir /newdir none bind)
gliderlabs, docker alpine page
github, issue 71 on smebberson/docker-alpine not fixed. pull request #88 and #89 submitted by kungfu71186 for fixing alpine-apache
stackoverflow, proper path to execute apk apache2 /usr/sbin/httpd
docker, use upper case letters for build arg names
vsupalov, docker and multi-stage building
NOTES
Get rootfs filesize of container, needs CR removal
sudo docker run -it -m 8m --memory-swap 8m alpine:latest /bin/df -h / | tr -d '\r' | grep -E "\s/$"
Creating a volume for an xfs loopback
docker volume create --driver local --opt type=xfs --opt device=/dev/loop5 xfs256