Part 3 — Introduction to Data Storage with Docker Volumes
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
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.