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-0
AWS instance with your supplied credentials, for example:ssh -i user23.pem [email protected]`
-
Pull down the official Nginx image.
$ docker pull nginx
-
Create a new volume named
barcelona
.$ docker volume create --name barcelona
Your new volume is created on the host in the
/var/lib/docker/volumes
directory. -
List the volumes on your Docker host
$ docker volume ls DRIVER VOLUME NAME local barcelona
You should see the
barcelona
volume listed. You may see other volumes as well. -
Instantiate a Docker container with your
barcelona
volume.$ docker run -it -v barcelona:/barcelona --name volumeslab nginx /bin/bash
This command creates an Nginx container named
volumeslab
. It also mounts your volumebarcelona
at/barcelona
in the root of the container's file system. Then, the/bin/bash
command opens an interactive shell inside the container.You are at your running container's shell prompt.
-
Change into the
/barcelona
directory.$ cd /barcelona
-
Create a file.
$ touch file.txt
-
List the directory contents to make sure the file exists.
$ ls file.txt
-
Press
Ctrl+P
andCtrl+Q
to 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 ps
The output should be similar to:
CONTAINER ID IMAGE COMMAND CREATED STATUS 0124480582a2 nginx "/bin/bash" 6 minutes ago Up 6 minutes
The
STATUS
should showUp
instead 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
barcelona
volume values.$ docker volume inspect barcelona
Your 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 su
You need superuser privileges to view the location of the Docker volume data in your host filesystem.
-
Change to the
barcelona
data directory.$ cd /var/lib/docker/volumes/barcelona/_data
-
List the directory contents.
$ ls file.txt
Notice the file you previously created
file.txt
is listed in the host directory. -
Create a new file.
$ touch file2.txt
-
Check that
file.txt
andfile2.txt
are 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
/barcelona
directory.$ ls /barcelona file.txt file2.txt
The file you created from the Docker host shell
file2.txt
should 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
volumeslab
container you created.$ docker stop volumeslab
-
Remove the container.
$ docker rm volumeslab
Removing the containers does not remove the
barcelona
volume the container was using. -
Ensure the
barcelona
volume still exists.$ docker volume ls DRIVER VOLUME NAME local barcelona
You may see other volumes listed in addition to
barcelona
. -
Elevate your privileges.
$ sudo su
-
List the contents of the
barcelona
volume directory.$ ls /var/lib/docker/volumes/barcelona/_data file.txt file2.txt
The 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 NAME
The*
barcelona
volume 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
www
subdirectory on your Docker host.$ mkdir ~/www
-
Change into the
www
directory.$ cd ~/www
-
Create an
index.html
file 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
~/www
directory.$ docker run -d -v ~/www:/usr/share/nginx/html --name mywebserver -p 80:80 nginx
This command maps the
~/www
directory on the host to/usr/share/nginx/html
in the running container. Theusr/share/nginx/html
is 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, Barcelona
message. -
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
foo
and mount theshared-data
volume.$ docker run -it -v shared-data:/foo --name foo nginx /bin/bash
This command mounts
shared-data
to the/foo
directory and logs you into the container's shell. -
Create a new file in the
/foo
directory.In the command below, be careful to use the right single quote (‘) and double quotes (").
$ echo 'Tu dices "hola"' > /foo/file.txt
The
/foo
directory is mapped to yourshared-data
volume. -
Verify the content of your new file.
$ cat /foo/file.txt Tu dices "hola"
-
Press
Ctrl-P
and thenCtrl-Q
on you keyboard.This exits the container shell but leaves the container running.
-
Create a second,
bar
container.The command mounts the existing
shared-data
volume to the container's/bar
directory and starts a shell.$ docker run -it -v shared-data:/bar --name bar nginx /bin/bash
You are now working in the shell of your Docker container.
-
Create a new file in the
/foo
directory.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
bar
container.$ exit
This closes the shell and stops the container.
-
Log back into the shell of the
foo
container.$ docker exec -it foo /bin/bash
You are now working in the shell of your Docker container.
-
Look for the changes you made in the
bar
container in this container.$ cat /foo/file.txt Tu dices "hola" Y yo digo "adios"
-
Exit and stop the
foo
container.$ 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