brandLogo

Tech Notes.

By Danish

Data persistence with docker volumes

By default containers store data inside their memory. This data get deleted along with container. And since data is stored inside the container, it can not be shared with other containers.

Issues summarized:

  • Data is volatile and lost with container
  • Data can't be shared with others

This is what volume solves for us


How exactly does that work on the inside?

When we mount a location to some volume, docker redirects the read and write on that path to the volume.

Let's assume that a container is trying to write something in app/data/info. Usually this data would be written inside container's file system. So that would be container-file-system/app/data/info. If we have mounted app/data/info to a volume, then when the container tries to write on this location, docker will redirect this operation to the volume. Since this data then remains outside container's file system, it remains independent of container life cycle.

I have created a simple app. It performs crud operation based and stores files in a json rather than a DB. This is just an example we are using this not whats done in production apps. But yes there we can have reports or config files in such setup.

Checkout this repo : https://github.com/dev-danish-javed/technotes-demo-code/tree/main/docker-demo/node-code/student-app

We have two prepopulated students there. We can use this postman collection to make calls and add more records and fetch e.t.c

Bootup ubuntu and naviagte to the repo. Let's create the docker images and containers

docker build -t student-app-a:v1.0 .
docker run --name student-app-1 -p 8989:3300 student-app-a:v1.0
docker run --name student-app-2 -p 9090:3300 student-app-a:v1.0

Now we have our app running in 2 containers. Its the same version. This is pretty common in production apps.

Let's go ahead add new student in app-1. We have the request in our postman collection. Now hit the endpoint to get student list in app-2. We don't have the newly added student there. This means :

  • Data is not being shared among our app
  • Data is not persisted. If we delete our container we'll loose all the data.

Let's try to generate and use volume to fix our issue

  1. Let's get rid of existing containers. docker stop student-app-1 student-app-2
  2. Let's get rid of existing containers. docker rm student-app-1 student-app-2
  3. Create a new volume docker volume create student-app-volume
  4. Verify volume with docker volume ls
  5. Let's start our apps
    • docker run --name student-app-1 -p 8989:3300 -v student-app-volume:/app/student-app/data student-app-a:v1.0
    • docker run --name student-app-2 -p 9090:3300 -v student-app-volume:/app/student-app/data student-app-a:v1.0
  6. Once both our instances are up, we can test the changes with postman collection
  7. Let's first test data sharing
    • Hit get all student records, for both the instances
    • Add new student in one instance and then check get all instance for other instance
    • We now see that data is being shared in the instances
    • Volume has solved data sharing problem for us. Now all the instances of our ms will have the same data
  8. Now time for persistence
    • Add a student with your name in the records, this'll be our marker
    • Let's remove our containers and recreate them
      • Stop containers docker stop student-app-1 student-app-2
      • Remove containers docker rm student-app-1 student-app-2
    • Create new containers, like we did in step 5
    • There we have our name in the list.
    • And that's how docker has solved data persistance for us
Cool now we understand what docker volumes are and what are they for 🥳🎉

This data won't be removed regardless of how many times we remove and add container. As long as the volume is intact, our data is safe.

But as of now you would have noticed, it's quiet a pain creating containers and passing them all the relevant args like port expose volumes names etc
Well that is what we are going to solve in the next section - Docker Compose