DEV Community

Fabio Oliveira Costa
Fabio Oliveira Costa

Posted on • Edited on

Introduction to container based development - Part 3/4 - Volumes

This is the third part of our container based development series

This post is based on the container development article created by me.

On the previous articles we did a program that count from 0 to 19 but could not do anything besides that. A program that can not persist is not so useful so let's modify our program a little so it will count the current file content and then count to that value +20. For that we need to create a volume on the container, this will make a specific folder on the container persist when mounted. All the files for this step are on the projects repository on the secondContainer branch.

First we need to add a proper volume on our docker file.

Dockefile

FROM node:13-alpine3.10
RUN mkdir -p /app/ourApp/data
COPY ./nodeCounter.js  /app/ourApp/
WORKDIR  /app/ourApp/
VOLUME /app/ourApp/data/
CMD node ./nodeCounter.js

Then we need to make sure our program don't stop at 20 but stops at start + 20

nodeCounter.js

const fs = require('fs')
const path = require('path')

const counterFile = path.resolve(__dirname, './data/counter.txt')

const COUNTER_LIMIT = 20
const INTERVAL = 1000
let counterData = 0
if (fs.existsSync(counterFile)) {
  const fileData = fs.readFileSync(counterFile)
  counterData = parseInt(fileData, 10)
}

const stopCounter = counterData + COUNTER_LIMIT

const recursiveCounter = () => {
  if (counterData === stopCounter) {
    process.exit(0)
  }
  console.log(counterData)
  counterData++
  fs.writeFileSync(counterFile, counterData)
  setTimeout(recursiveCounter, INTERVAL)
}

recursiveCounter()

Then we need to build our image with the same name and a new tag.

docker build -t container_dev:second  .

We should see an output with the text:

"Successfully tagged container_dev:second"

But out work is not over we need to actually create a volume on our computer (the host) so our container can read and write persistent data.

docker volume create our-named-volume

But where physically our volume is? For that we can inspect the volume and check it's exact path.

docker volume inspect our-named-volume

That would give all the volume data like the one below, the mountpoint is where docker created our volume.

[
    {
        "CreatedAt": "2020-03-20T10:44:48+01:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/our-named-volume/_data",
        "Name": "our-named-volume",
        "Options": {},
        "Scope": "local"
    }
]

Now to run our app with one new argument , -v to link the volume

docker run -v our-named-volume:/app/ourApp container_dev:second

Run it twice and you will notice we start where we stopped. If you open 2 shells and do it a little bit after the first one start you should see they are sharing and modifying the same file (There is a race condition here but we don't mind for now).

We have a way to persist state, actually we even have a way to share the same set of files between multiple containers!

I would like to call attention about the importance of mounting, if we run without the "-v" command we will have the same behavior as the first time, our state would not persist.

So let's see what we learned

  • For a volume to be accessible in the container we need to create it at some location inside the container.
  • We need to link a volume with the -v when running the docker run argument.
  • Multiple containers can have access to the same volume.

Next part: Containers and installing PHP alongside node in 16 lines of code!

Top comments (0)