Difficulty: Intermediate
Time: 30 minutes
Tasks
- Prerequisites
- Task 1: Implementing a volume via the Docker client
- Task 2: Understand how Docker represents volume data in the file system
- Task 3: Deleting a volume
- Task 4: Map a host directory to a Docker volume
- Task 5: Use a volume to share data between containers
A data volume is a specially designated directory within one or more containers that bypasses Docker’s storage driver and interacts directly with the host file system. Data volumes provide several useful features for persistent or shared data:
- Volumes are initialized when a container is created. If the container’s base image contains data at the specified mount point, that existing data is copied into the new volume upon volume initialization.
- Data volumes can be shared and reused among containers.
- Changes to a data volume are made directly to the host filesystem (vs. going through the storage driver)
- Changes to a data volume will not be included when you update an image.
- Data volumes persist even if the container itself is deleted.
Data volumes are designed to persist data, independent of the container’s lifecycle. Docker therefore never automatically deletes volumes when you remove a container, nor will it "garbage collect" volumes that are no longer referenced by a container.
For this lab, please use node-0 and ensure no containers are running on that node. To check for running containers use the docker ps command.
In this task, you're going to create a new container and add a file to it.
-
SSH into your
node-0AWS instance with your supplied credentials, for example:ssh -i user23.pem ubuntu@ec2-52-24-109.us-west-2.compute.amazonaws.com` -
Pull down the official Nginx image.
$ docker pull nginx -
Create a new volume named
barcelona.$ docker volume create --name barcelonaYour new volume is created on the host in the
/var/lib/docker/volumesdirectory. -
List the volumes on your Docker host
$ docker volume ls DRIVER VOLUME NAME local barcelonaYou should see the
barcelonavolume listed. You may see other volumes as well. -
Instantiate a Docker container with your
barcelonavolume.$ docker run -it -v barcelona:/barcelona --name volumeslab nginx /bin/bashThis command creates an Nginx container named
volumeslab. It also mounts your volumebarcelonaat/barcelonain the root of the container's file system. Then, the/bin/bashcommand opens an interactive shell inside the container.You are at your running container's shell prompt.
-
Change into the
/barcelonadirectory.$ cd /barcelona -
Create a file.
$ touch file.txt -
List the directory contents to make sure the file exists.
$ ls file.txt -
Press
Ctrl+PandCtrl+Qto exit the container shell.This key combination leaves the container running. You should return to your Docker host's shell.
-
Ensure your container is still running:
$ docker psThe output should be similar to:
CONTAINER ID IMAGE COMMAND CREATED STATUS 0124480582a2 nginx "/bin/bash" 6 minutes ago Up 6 minutesThe
STATUSshould showUpinstead ofExited
Docker manages volumes independently from the storage driver system it uses to manage the container layers. This allows for data persistence; The volume is not destroyed when the container is destroyed.
In this task, you're going to take a quick look at where Docker stores volume data. Then, you'll change the volume on the Docker host file system and see the change made back in the container.
-
Inspect the
barcelonavolume values.$ docker volume inspect barcelonaYour output should be similar to: [ { "Name": "barcelona", "Driver": "local", "Mountpoint": "/var/lib/docker/volumes/barcelona/_data" } ]
The volume mount point above is:
/var/lib/docker/volumes/barcelona/_data -
Elevate your user privileges:
$ sudo suYou need superuser privileges to view the location of the Docker volume data in your host filesystem.
-
Change to the
barcelonadata directory.$ cd /var/lib/docker/volumes/barcelona/_data -
List the directory contents.
$ ls file.txtNotice the file you previously created
file.txtis listed in the host directory. -
Create a new file.
$ touch file2.txt -
Check that
file.txtandfile2.txtare in the directory.$ ls file2.txt file.txt -
Log back into the Nginx container's shell.
$ docker exec -it volumeslab /bin/bash -
List the contents of the
/barcelonadirectory.$ ls /barcelona file.txt file2.txtThe file you created from the Docker host shell
file2.txtshould also appear inside your running container. -
Exit the container and return to your Docker host.
$ exit
By default, when you destroy a container Docker does not remove any volumes associated with the container. You can, however, delete a given volume with the docker volume rm command.
-
Stop the
volumeslabcontainer you created.$ docker stop volumeslab -
Remove the container.
$ docker rm volumeslabRemoving the containers does not remove the
barcelonavolume the container was using. -
Ensure the
barcelonavolume still exists.$ docker volume ls DRIVER VOLUME NAME local barcelonaYou may see other volumes listed in addition to
barcelona. -
Elevate your privileges.
$ sudo su -
List the contents of the
barcelonavolume directory.$ ls /var/lib/docker/volumes/barcelona/_data file.txt file2.txtThe volume and its data are still intact.
-
Exit elevated privileges.
$ exit -
Remove the volume.
$ docker volume rm barcelona barcelona -
Ensure the volume was removed.
$ docker volume ls DRIVER VOLUME NAMEThe*
barcelonavolume is no longer listed, although other volumes may be.
In the previous exercises, you were able to manipulate data files in a Docker volume via the host file system,. However, it was a bit cumbersome. You had to learn the mount point via docker volume inspect and elevate your privileges to create a new file. In practice, this workflow is impractical.
Thankfully there is an easier way to make local files available inside a running container. You can, instead, mount existing local files and directories as volumes into a running container. This allows developers, for instance, to hot-mount code into their containers, and have changes made locally reflected instantaneously in their containers.
In this example, you'll create two containers foo and bar. You'll modify some HTML in bar and then see how the changes are reflected immediately on the container-based website in foo. Additionally, you'll create a volume using the -v option with the docker run command. The lab switches between the containers so stay sharp as you read!
-
Create a
wwwsubdirectory on your Docker host.$ mkdir ~/www -
Change into the
wwwdirectory.$ cd ~/www -
Create an
index.htmlfile with some content.Be sure to use single quotes in the command/
$ echo '<h1>Hola Barcelona!</h1>' > index.html -
Instantiate an Nginx container with the
~/wwwdirectory.$ docker run -d -v ~/www:/usr/share/nginx/html --name mywebserver -p 80:80 nginxThis command maps the
~/wwwdirectory on the host to/usr/share/nginx/htmlin the running container. Theusr/share/nginx/htmlis the default directory for serving web content with Nginx. -
In your browser navigate to the
http://<docker host>address.For the,
<docker host>use the name provided to you when you signed up for this lab. Your browser should display a website with yourHello, Barcelonamessage. -
Return to your Docker host’s terminal window.
-
Update the index.html file.
Be sure to use single quotes as shown.
$ echo '<h1>Adios Barcelona!</h1>' > index.html -
Reload your website in your browser,
The change to the local filesystem is immediately reflected by the running Nginx container.
You can also use volumes to share data between containers. For instance, one container could write data to a log file, and a second container could read that data and provide a graphical interpretation.
In this example, you'll create a new file from one container in a directory that is a mount point for a named container. Then, you'll list the directory from another container.
Note: This example is purely for academic purposes. In a real-world deployment, it’s extremely dangerous to have multiple containers writing to the same volume without adequate application awareness and protection against conflicts.
-
Create a new named volume
shared-data.$ docker volume create --name shared-data shared-data -
Create a new container
fooand mount theshared-datavolume.$ docker run -it -v shared-data:/foo --name foo nginx /bin/bashThis command mounts
shared-datato the/foodirectory and logs you into the container's shell. -
Create a new file in the
/foodirectory.In the command below, be careful to use the right single quote (‘) and double quotes (").
$ echo 'Tu dices "hola"' > /foo/file.txtThe
/foodirectory is mapped to yourshared-datavolume. -
Verify the content of your new file.
$ cat /foo/file.txt Tu dices "hola" -
Press
Ctrl-Pand thenCtrl-Qon you keyboard.This exits the container shell but leaves the container running.
-
Create a second,
barcontainer.The command mounts the existing
shared-datavolume to the container's/bardirectory and starts a shell.$ docker run -it -v shared-data:/bar --name bar nginx /bin/bashYou are now working in the shell of your Docker container.
-
Create a new file in the
/foodirectory.Be careful to use the right single quote (‘) and double quotes ("). Also, be sure to use `>>` double pipes otherwise you will overwrite your original file. $ echo 'Y yo digo "adios"' >> /bar/file.txt -
Verify the content of your new file.
$ cat /bar/file.txt Tu dices "hola" Y yo digo "adios"The text you created in the first container (
Tu dices "hola") is still accessible in this container as well as the text you just added (Y yo digo “adios”). -
Exit the
barcontainer.$ exitThis closes the shell and stops the container.
-
Log back into the shell of the
foocontainer.$ docker exec -it foo /bin/bashYou are now working in the shell of your Docker container.
-
Look for the changes you made in the
barcontainer in this container.$ cat /foo/file.txt Tu dices "hola" Y yo digo "adios" -
Exit and stop the
foocontainer.$ exit
In this lab, you learned the basics of Docker volumes. You created a new Docker volume using the Docker client, and then explored the host file system to understand the relationship between the local file system and the mounted volume in the container. You then deleted our volume, and mapped a new volume to a specific directory on the host file system. Finally we looked at how you can share a volume between multiple containers.
Feel free to continue exploring Docker volumes.
If you plan to do another lab, you need to cleanup your EC2 instances. Cleanup removes any environment variables, configuration changes, Docker images, and running containers. To do a clean up,
-
Log into each EC2 instance you used and run the following:
$ source /home/ubuntu/cleanup.sh