Skip to content

Volumes

Append Volumes to Containers.

What you will learn:

  • Use cases to employ Volumes properly
  • Append Volumes to Containers
  • Bind Volumes


1. Bind Docker Volumes

Volumes in Docker are a practical feature for development scenarios.

A Volume is a kind of link between persisted files and the resembling files on the container. When declaring files or whole directories to be part of a volume, these will be updated close to real time on your container. Therefore, we can have our container running, while making changes to the local codebase. Consequently we do not have to rebuild the container every time to see the effect of a change.

Let’s see that in action.

You can access the project folder under reference/4-volumes and build an image from the Dockerfile. It’s the same setup as in Chapter 2. Name the image volume-test. You do not need to specify a version for this example.


Solution

1. Move into the correct directory:

$ cd exercise/docker/reference/4-volumes

2. Build the image:
$ docker buildx build -t volume-test .


Now, run the image and see if the content is displayed correctly. Name the container static and expose it on port 8083.


Solution

1. Run the container:

$ docker run -p 8083:80 -d --name static volume-test


We just followed the same procedure as before. It’s for demonstration purposes only. Now, access the application on localhost:8083 (or code.your-petname.your-comapny.k8s.workshop.thinkport.digital).

Check, if the page content is aligning with the content of the index.html file under reference/4-volumes.

Next, edit the reference/4-volumes/index.html file and refresh the page in your browser. Do you see any changes? Discuss the result.


HINT

- The container resembles the state of the codebase at the time the container was built.
- Any changes to the codebase after the docker build will not be projected to the container


With that knowledge, we want to implement a Docker Volume now, to dynamically load altered content of the index.html file! Remember that the idea behind Volumes is to persist data. In this case we make use of it to always grab the most recent version of our code.

There are of course other use cases that will be mentioned later.

Read up on Docker Volumes on the official Docker Documentation. Then, create and start another container with the volume-test image. Make use of the --volume or -v option to create a link between your local version of the index.html and the version on the container. Name the container dynamic and expose it on port 8084.


HINT

1. Put together the pieces and write the complete docker run command:

  • image: volume-test
  • name: dynamic
  • port: 8084:80
  • detached mode
  • volume: link reference/4-volumes/index.html to /usr/share/nginx/html/index.html

1. You need to use the absolute path for the volumes hostpath
Solution

/home/training/exercise/docker/reference/4-volumes/index.html:/usr/share/nginx/html/index.html
or
$(pwd)/index.html:/usr/share/nginx/html/index.html


Solution

$ docker run -d -p 8084:80 -v $(pwd)/index.html:/usr/share/nginx/html/index.html --name dynamic volume-test


Alright, call up the webpage of the dynamic container at localhost:8084 (or http://code.vm0.c<your-id>.f1.k8s.workshop.thinkport.cloud:8084). Again, edit the content of the image.html and refresh the page. What do you expect to happen?

Discuss the result. Also think about other implementations of volumes as persistent state.

Pretty nice, right?! Well, the setup is very simple so that the impact is quite low. But let us improve the application from Chapter 3 as well!



2. Managed Volumes

Go Example App

We will use our already introduced guestbook app in this exercise. Please build the image of the app and tag it with go-app:volume. Go to the docker/go-app directory. The Dockerfile is located in docker/reference/4-managed-volumes, but you need to execute the docker build command from the main directory. Do you remember how to do this?

Some details about the app:

  • its web interface listens on port 8080.
  • with the configured environment variables in the Dockerfile the app will save the entered messages in a json file located at /messages/messages.json.
Solution

$ cd docker/go-app
$ docker buildx build -f ../reference/4-managed-volumes/Dockerfile -t go-app:volume .

Run the app without volume

Now we want to see our example application in action:

  • start a container running the application, map it from port in the container 8080 to port 8085
  • enter some messages
  • stop the container
  • restart the container
Solution
$  docker run -p 8085:8080 go-app:volume

Discussion

What do you expect from the steps above? Stop and delete the intermediate container now.

Persist data with managed volume

In this step we want to create a managed volume and mount it to /messages in the container of our example app. Please do the following:

  • create a volume using the docker cli named messages
  • spin up a container
  • called go-app-volume
  • forwards port 8080 to port 8085 again
  • with a mount of the volume messages at /messages
HINT

Read the volume documentation at docker.com

Solution
$  docker volume create messages
$  docker run -p 8085:8080 -v messages:/messages/ --name go-app-volume go-app:volume

Now create a second container go-app-volume-2 that forwards port 8080 to 8086 on your local machine, but mounts the same volume.

Solution
$  docker run -p 8086:8080 -v messages:/messages/ --name go-app-volume-2 go-app:volume

Discussion

Let’s discuss the results together!

Additional Information

It is also possible to use the --mount flag instead of the --volume flag. The mount flag allows more advanced configurations, e.g. for network shares. Furthermore it is possible to set volumes to read-only if you want to protect the data inside them. This is often used for volumes that initialise services (e.g. dbms). Another important behaviour of docker is to copy the content of the mounted path in the image to an empty volume by default (if the path already exists in the image). You may want to suppress this behaviour. You can find more information about this topic in the docker documentation.

END