Search code examples
dockerstoragepersistencedocker-volume

docker persistent storage via volume


All that read are saying that we can create docker persistent storage via the VOLUME control, e.g., here and here.

However, I have the following in my Dockerfile:

VOLUME      ["/home", "/root"]

but nothing was kept in there (I tried touch abc, and when I exit and get back in again the file is not there).

I see that the official usage has no other special controls or treatments, yet it can provide persistent storage, even the apt-cacher-ng service container is stopped.

How is that possible? I've checked out the following but still don't have a clue:

In conclusion, as explained here:

The first mechanism will create an implicit storage sandbox for the container that requested host-based persistence. ... The key thing to understand is that the data stored in the sandbox is not available to other containers, except the one that requested it.

How can I make persistent storage works? Why my changes are wiped each time, while the apt-cacher-ng service container can maintain its persistent storage even it is stopped and restarted? What is the "other special controls or treatments" that I failed to see here?

Explain with plain simple Dockerfile (not docker-compose.yml ) please.


Solution

  • The problem is that the VOLUME instruction creates an external storage when the docker run is used without the "mount" option for that specific folder. In other words, every time you create a container for that image, docker will create a new volume with a random label but since you're not giving those volumes a name, the new containers cannot re-use the existing generated volumes.

    e.g.

    FROM ubuntu
    RUN mkdir /myvol
    RUN echo "hello world" > /myvol/greeting
    VOLUME /myvol
    

    Given this Dockerfile, if you simply build and run this docker image using the following commands:

    echo "There are currently $(docker volume ls | wc -l) volumes"
    
    docker build -t my_volume_test:latest .
    docker run --name another_test my_volume_test:latest
    
    echo "There are currently $(docker volume ls | wc -l) volumes"
    

    you'll see that the amount of volumes present on your machine has increased. That container is now using a volume to store the data but that specific volume does not have a name or label so it's only bound to that specific container. If you delete and recreate that container, docker will generate a new volume with a random name unless you manage to mount the volume you've created earlier.

    If you want to make it easy, I suggest to first create the volume and mount it then. e.g.

    docker rm -f another_test
    docker volume create my-vol
    
    docker run \
        --name another_test \
        --mount source=my-vol,target=/myvol \
        my_volume_test:latest
    
    # alternative
    docker rm -f another_test
    docker run \
        --name another_test \
        -v my-vol:/myvol \
        my_volume_test:latest
    

    In this case you can create and remove as many containers you want but they'll all use the same volume.

    check the VOLUME reference and Use volumes for more info.