Part 3 — Introduction to Data Storage with Docker Volumes

John Olafenwa
Dev Planet
Published in
4 min readSep 3, 2019
Image source: https://www.salon.com/2018/07/11/never-worry-about-running-out-of-cloud-storage-again/

Docker and a lot of tools in the cloud native world are aimed primarily at highly distributed stateless applications. Stateless apps are easier to manage at scale and the general approach to building modern applications that needs to persist data is to have the data storage service such as database servers managed and hosted separately from the application. This decoupling allows us to manage deployments easily and the app is often connected to external storage services via service URIs.

However, for practical reasons, sometimes we need to store data permanently in docker containers. A simple example is a small scale webapp which stores its data in an embedded SQLite database.

When you run a container, every data it generates or stores only lives as long as the container. The moment the container is removed, the data is lost. To enable permanent data storage, docker has a feature called, “Volumes”.

Docker volumes act like an external hard disk you can attach to your container.

In this tutorial, we shall go through how to use docker volumes to persist data for a simple web app using SQLite as its database.

Building an Endgame Review Website With Docker

Image source: https://www.marvel.com/movies/avengers-endgame

Yeah! You read that right, we are creating a review site for Avengers Endgame. This site would allow users submit reviews and view submitted reviews. All the data would be stored in an SQLite database and persisted using docker volumes.

You will find this example in the DevPlanet repo

To build this example, follow the steps below.

Step 1: Clone DevPlanet

git clone https://github.com/johnolafenwa/devplanet

Step 2: CD to the Endgamereview Directory

cd devplanet/samples/docker/endgamereview

These app is made up of a number of files, all of which you will find in the folder stated above.

Below is the app.py

As seen from DATA_PATH = “/database”, we are storing the sqlite database file in a directory named /database within our container.

Dockerfile

FROM python:3.6-slimWORKDIR /appCOPY . /appRUN pip3 install -r requirements.txtEXPOSE 5000CMD [“python3”,”app.py”]

The Dockerfile is same as in part 1 of this series.

Step 3: Build

sudo docker build -t endgamereview .

Step 4: Run With A Volume Attached

sudo docker run -v datavolume:/database -p 80:5000 --name endgame endgamereview

In the above, -v datavolume:/database maps a docker volume named datavolume to the /database directory within the container. The name of the volume can be anything you choose, the first time you run this, the volume with the given name would be automatically created. All data you write to the /database directory would be stored in this volume, ensuring that anytime you run your image with the same volume name attached, all data previously written to the /database directory is permanently persisted.

View your running site

Visit localhost:80 on your system

After submitting a review, you should see the reviews page appear like below

To demonstrate the persistence enabled by docker volumes, we shall remove the container named endgame above and start it again.

sudo docker stop endgame && sudo docker rm endgame

Now run it again,

sudo docker run -v datavolume:/database -p 80:5000 --name endgame endgamereview

Visit localhost/reviews and you would see the reviews you previously submitted.

You should try running these without the volume attached and you would see how the reviews clears out on every run.

Multi Volume Mappings

It is generally a good idea to have a master directory within your container and map a single volume to these master directory. With these, you can create multiple sub directories for different purposes and have all of them in one volume. However, if you so desire, you can map multiple volumes to multiple directories within your container. Below is an example mapping a database and a log directory to two volumes.

sudo docker run -v datavolume:/database -v logvolume:/logs -p 80:5000 endgamereview

Creating Volumes

While volumes are automatically created the first time you use them, you can also explicitly create new volumes using the command below.

sudo docker volume create my_new_volume

Listing Created Volumes

You can view the list of all previously created docker volumes using

sudo docker volume ls

Deleting Volumes

You can permanently delete a volume along with all of its stored data

sudo docker volume rm my_new_volume

Summary

Docker volumes offer a simple way to build stateful containerized applications. Volumes can be shared across multiple containers and even multiple hosts. In this tutorial, we applied docker volumes to persist data for a SQLite based application. In more practical scenarios, you will need docker volumes to store application logs, host containerized database servers etc. In a typical deployment scenario, you can have a set of containers running your main application and another set of containers running a database server. On docker hub, you will find ready to run docker images for almost any database server you dream of using, all of them use docker volumes to persist their data and often involve multiple volume mappings.

In the next tutorial, we shall focus on deploying docker containers in production using docker compose.

--

--