Docker Community Forums

Share and learn in the Docker community.

What's the difference between adding volume in a Dockerfile and running an image with volume?

Hello!

this is my question What’s the difference between adding volume in a Dockerfile and running an image with that volume instead? (assuming it’s always the same volume)

thanks!

Having VOLUME in Dockerfile allows you to specify that a path inside the image should always be created as a volume (to bypass the union filesystem Docker uses by default). e.g., this is common for database images where writing to /var/lib/postgresql on AUFS vs. something like EXT4 wouldn’t make sense (the data directory doesn’t have any reason to be in the union filesystem and imposes a big R/W performance hit). That way, users of the image will always get a volume there if they docker run, without having to remember to “Oh yeah, and -v /var/lib/postgresl on this docker run command as well”.

Bind mounts (-v /tmp:/tmp) and named volumes (-v name:/foo) are not allowed to be specified in Dockerfile since they are not portable.

Thanks for the replay @nathanleclaire !

as I see it after this is for convenience, is there any performance difference?

Not between VOLUME ["/foo"] and -v /foo. They are the exact same in effect.

thanks again! :slight_smile:

1 Like

@nathanleclaire: I am new to docker and my understanding of the two are a bit shaky at the moment, could you please kindly confirm if my following assumptions are accurate (and which are not and why):

  1. VOLUME in Dockerfile will create (and overlay if it already exists) the specified directory as a volume (residing externally from the main container) when the main container is started.

e.g. VOLUME ["/temp-volume-outside-of-main-container"] in the Dockerfile used to build the container image will create an external docker volume and overlay it at the location /temp-volume-outside-of-main-container every time the container is started.

  1. On its own, the VOLUME in Dockerfile does not function as any HOST DIR:Container interface (host drive mounting) or Volume:Container (Data Volume Container mounting); i.e. it serves the same as:

DOCKER RUN -v /temp-volume-outside-of-main-container […] imagename

This implies that if the container imagename is stopped and started again (e.g. from a computer reboot):

  • the imagename container will create another /temp-volume-outside-of-main-container upon starting,
  • stopping and starting the container will discard any data changes made in the previous session to /temp-volume-outside-of-main-container,
  • when the imagename container starts up again, it will create a brand new volume for /temp-volume-outside-of-main-container instead of mounting the previous session’s volume.
  1. The -V command in DOCKER RUN functions the same as VOLUME in Dockerfile if used as mentioned in assumption 2.

  2. The -V command in DOCKER RUN also has an additional functionality which allows you to map a (or multiple) host drive(s) or separate docker container(s) to a particular path inside the imagename container as follows:

  • DOCKER RUN -v HOSTdirectory:/volume-inside-main-container […] imagename
    OR
  • DOCKER RUN --volumes-from (ExtContainerID)/(ExtContainerName):/volume-inside-main-container […] imagename

This allows for data persistence in the host directory or another shared docker container, respectively.

  1. DOCKER RUN -v and DOCKER RUN --volumes-from are identical with the exception that -V mounts from the host directory whereas –volumes-from mounts from a separate docker container.

  2. The VOLUME in Dockerfile is only used when Dockerfile is used, i.e. when the image is first built and published. Anyone pulling that already existing image from DockerHub or some other source will already have assumption 1 applied automagically for them.

  3. For the reason of assumption 6, Dockerfiles cannot have ‘mounting’ integrated into it as mounting is dependent on either the Host DIR/Docker environment, meaning its mutable and we don’t like random variables. It also makes sense that the mounting should begin when the user boots up the container.

Perspective: I am currently attempting to use Docker as an app-deployment tool so that clients can double-click a desktop icon which will boot up a docker container, mount an existing data volume to the container (database dvc) and access the database dvc from the main container’s apps.

Many thanks!