Docker: Working with local volumes and tmpfs mounts

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

docker, volumes

docker, bind mounts

docker, tmpfs mounts

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

alpine, apk libraries search

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