Does docker run -v or Dockerfile VOLUME take precedence?

Dockerfile

FROM nginx:1.7

# Deliberately declaring VOLUME before RUN
VOLUME /var/tmp

RUN  touch /var/tmp/test.txt

Observation

Now I believe I understand the implications of declaring the VOLUME statement before
creating test.txt - the volume /var/tmp exposed at runtime will be based on the intermediary container prior to the test.txt file is created so it will be empty (hope this observation is correct)

So as expected the following docker run does not show test.txt:

docker run kz/test-volume:0.1

But then I tried supplying the volume at runtime as below:

docker run -v /var/tmp kz/test-volume:0.1

Question

The outcome was the same. So what does this mean? does the -v /var/tmp in the docker run command map to the empty /var/tmp dir exposed by the VOLUME command in the Dockerfile and not the /var/tmp directory with the test.txt in the latest image?

Feeling a tad bit confused.

As a general answer to your question: docker run options take precedence over anything in the Dockerfile; but some options (like -v/VOLUME) are additive, plus you’ve asked about a special case.

Dockerfile reference | Docker Docs agrees with you: /var/tmp is always empty, and your touch command does nothing.

These two commands are identical; the first one gets an implicit -v /var/tmp option from the VOLUME statement in the Dockerfile.

Finally, there’s one more special case.

cat >Dockerfile <<EOF
FROM ubuntu:16.04
RUN mkdir /x && touch /x/y
VOLUME /x
CMD ls -l /x
EOF

docker build -t my/image .

docker run my/image
# shows /x/y

mkdir $PWD/y
docker run -v $PWD/y:/x/y my/xmage
# shows nothing

In the first case where Docker implicitly creates the volume, it is populated from the volume that was “baked in” to the image. In the second case where you provide an explicit host directory, there is no automatic population.