1

According to the Docker documentation regarding the VOLUME instruction:

The docker run command initializes the newly created volume with any data that exists at the specified location within the base image. For example, consider the following Dockerfile snippet:

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

This Dockerfile results in an image that causes docker run to create a new mount point at /myvol and copy the greeting file into the newly created volume.

I am unable to replicate this behaviour using this exact Dockerfile and running:

$ docker run --volume ~/testdir:/myvol 159b3387c7eb

The testdir directory is created by does not contain the expected greeting file.

What am I doing wrong ?

Community
  • 1
  • 1
Malobre
  • 57
  • 2
  • 7
  • 1
    As far as I know `--volume` replaces the volume with whatever's in `~/testdir` in your case. It swaps out whatever was baked into the container image. – tadman Nov 12 '19 at 20:47

2 Answers2

4

There are several types of volumes:

  1. Host volume, which bind mounts a directory from the host into a container. Docker never initializes these. Whatever the state of the host becomes the directory contents in that directory. This is the type of volume you created. They have the downside of having uid/gid permission issues when the container uid/gid does not match that of your host user.

  2. Anonymous volume, which is a named volume with a long guid for a name. There is no information of what the target of an anonymous volume was, especially when the container has been deleted, so you'll want to give your volumes a name at least. These are the default if you define a volume with VOLUME and then forget to define a volume when running the container.

  3. Named volume, which is created by giving it a valid name rather than a path as a source. These are recommended for most scenarios, unless you need external access to your data with a host volume. The advantage of named volumes is that docker initializes them upon creation to the contents of your image at that location. This initialization only happens when the volume is first created, so changes to the image will not be reflected unless you have something like an entrypoint to copy data from another directory back out to your volume.

If you want to see a named volume with the data initialized, that would look like:

$ docker run --volume testvol:/myvol 159b3387c7eb

to create a volume called testvol.

BMitch
  • 231,797
  • 42
  • 475
  • 450
0

When you declare a VOLUME that doesn't pre-populate the volume with anything, it just describes an intended mount-point.

When you call Docker with the --volume argument it replaces anything in that target directory with your local directory, effectively mounting that local directory on top of the target location. Anything in that original location is obscured by the mount and inaccessible.

If you need to pre-populate the volume with content either do it before you mount it, or have an ENTRYPOINT script that initializes that directory when the container boots up.

tadman
  • 208,517
  • 23
  • 234
  • 262
  • 1
    https://docs.docker.com/storage/volumes/ Section "Populate a volume using a container": says that it is supposed to populate the volume before mounting it, am I understanding this wrong ? – Malobre Nov 12 '19 at 20:58
  • 1
    The data will persist *unless you replace it* with the `--volume` directive. The data is there if you don't mount, presumably. Maybe I'm misunderstanding the situation here, but I've always seen Docker replacing any mounts with the dynamic ones specified. – tadman Nov 12 '19 at 21:00
  • Okay that makes sense, reading their example a second time they're only using `--volume` to name the volume. – Malobre Nov 12 '19 at 21:04
  • 1
    It's kind of confusing, I thought you could pre-populate volumes based on the documentation like you did, but in practice that doesn't seem to be the case. – tadman Nov 12 '19 at 21:06
  • This answer is wrong. VOLUME **does** create a volume. More over it copies data from the image to that volume. See https://docs.docker.com/engine/reference/builder/#volume. However, the problem is it only does it for newly created docker volumes and *not* bind mounts. – spinkus Feb 23 '22 at 17:55
  • @spinkus Please add your own answer. I am unable to delete this one. – tadman Feb 24 '22 at 13:45