Docker Volume Persistence not working for more than one run of a container

Viewed 71

Docker version 20.10.2

I'm just starting out on Docker and following training guides - but something hasn't been mentioned so far (that I have discovered) - when I run a container to write some data out to Docker volume, if I run that container again and attach to the same volume, the newly named data will not append into it ?

Here is my rather basic Dockerfile

FROM ubuntu

RUN mkdir applocal

RUN touch applocal/applocalfile."$(date --iso-8601=seconds)"

RUN ls -la applocal

I run this sequence of commands...

docker build Dockerfile -t mine/applocal-persist
Sending build context to Docker daemon  2.048kB
Step 1/4 : FROM ubuntu
 ---> c29284518f49
Step 2/4 : RUN mkdir applocal
 ---> Running in 9f796f4d988a
Removing intermediate container 9f796f4d988a
 ---> 99005a7ffed1
Step 3/4 : RUN touch applocal/applocalfile."$(date --iso-8601=seconds)"
 ---> Running in ffbf2f4c636a
Removing intermediate container ffbf2f4c636a
 ---> 199bc706dcc6
Step 4/4 : RUN ls -la applocal
 ---> Running in 7da02faa9fba
total 8
drwxr-xr-x 1 root root 4096 Jul 16 13:52 .
drwxr-xr-x 1 root root 4096 Jul 16 13:52 ..
-rw-r--r-- 1 root root    0 Jul 16 13:52 applocalfile.2021-07-16T13:52:00+00:00
Removing intermediate container 7da02faa9fba
 ---> 7387c521d82b
Successfully built 7387c521d82b
Successfully tagged mine/applocal-persist:latest

Then run the command...

docker run -v applocalsaved:/applocal mine/applocal-persist

Looking at the Volume data it has worked

ls -la /var/lib/docker/volumes/applocalsaved/_data/
total 8
drwxr-xr-x 2 root root 4096 Jul 16 14:55 .
drwxr-xr-x 3 root root 4096 Jul 16 14:55 ..
-rw-r--r-- 1 root root    0 Jul 16 14:52 applocalfile.2021-07-16T13:52:00+00:00

If I wait a few minutes later and re-run docker run -v applocalsaved:/applocal mine/applocal-persist

...and check the volume data again, no new file exists

ls -la /var/lib/docker/volumes/applocalsaved/_data/
total 8
drwxr-xr-x 2 root root 4096 Jul 16 14:55 .
drwxr-xr-x 3 root root 4096 Jul 16 14:55 ..
-rw-r--r-- 1 root root    0 Jul 16 14:52 applocalfile.2021-07-16T13:52:00+00:00

Run history...

docker ps -a
CONTAINER ID   IMAGE                   COMMAND   CREATED          STATUS                      PORTS     NAMES
6d16e9aa495e   mine/applocal-persist   "bash"    57 seconds ago   Exited (0) 55 seconds ago             distracted_cohen
69ff06d9c886   mine/applocal-persist   "bash"    2 minutes ago    Exited (0) 2 minutes ago              affectionate_lehmann

I've listed the Volume Inspect here...

docker volume inspect applocalsaved
[
    {
        "CreatedAt": "2021-07-16T14:55:24+01:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/applocalsaved/_data",
        "Name": "applocalsaved",
        "Options": null,
        "Scope": "local"
    }
]

I'm obviously missing a trick here - or misunderstanding what is going on or the design around this.

Thanks in advance

For info: I'm using Windows running Virtual Box and running Ubuntu 21.04 as a VM

2 Answers

The commands in the Dockerfile only run once, when the image is originally built. You can verify this for example by just running the image without a volume mount:

docker build -t mine/applocal-persist .
docker run --rm mine/applocal-persist \
  ls -l ./applocal
sleep 60
docker run --rm mine/applocal-persist \
  ls -l ./applocal

If you start the container with a named volume mounted, only if the volume is a Docker named volume and only if the volume is empty, the contents of the image will be copied into the volume. (This doesn't happen on Docker bind mounts, Kubernetes volumes, or if the image has changed; I would not rely on this for any sort of data sharing since it works in so few contexts.)

Conversely, if you start the container with any sort of volume mounted, whatever content is in the volume completely replaces what's in the image. You can see this with some more experimentation:

# Build the image
docker build -t mine/applocal-persist

# Start the container with a new named volume mounted; see what's there.
docker volume rm applocalsaved
docker run --rm -v applocalsaved:/applocal mine/applocal-persist \
  ls -l /applocal

# Edit a file in the volume and see that it gets persisted across restarts
docker run --rm -v applocalsaved:/applocal mine/applocal-persist \
  touch /applocal/foo
docker run --rm -v applocalsaved:/applocal mine/applocal-persist \
  ls -l /applocal

# But it is not included in the image without the bind mount
docker run --rm mine/applocal-persist \
  ls -l /applocal

sleep 60

# Rebuild the image
docker build -t mine/applocal-persist

# In the base image, you will see the updated timestamp
docker run --rm mine/applocal-persist \
  ls -l /applocal

# But if you mount the volume, the old volume contents replace the
# image contents and you will only see the old timestamp
docker run --rm -v applocalsaved:/applocal mine/applocal-persist \
  ls -l /applocal
Related