Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do some Docker images have no VOLUME defined?

I am just starting with Docker, please pardon me if my question is too silly for you.

I see some images, like nginx, does not have any VOLUME defined whereas some images like mysql has VOLUME defined in their Dockerfile.

How the data or files are managed when there is no volume defined, and what would be their working directory?

like image 922
s3-89 Avatar asked Sep 06 '25 07:09

s3-89


2 Answers

A preferred pattern for many applications you can run in a container is to store no state at all locally. If I have a Web application, and perhaps it takes a configuration file as input, but it stores all of its data in an external database, I need no local storage. In turn, that means that I can run several copies of it for redundancy or to support larger scales, and I don't need to worry about preserving data if I need to replace a container. If my containers are in fact stateless, then I have no need for a VOLUME (or to attach volumes to my container at runtime).

Even if your container does have local state, you probably don't want VOLUME. What VOLUME actually means is, when a container runs, if nothing else is mounted on the named filesystem path, create an anonymous volume and mount it there (letting Docker populate it from image content). In practice, this means:

  • You can use docker run -v or Docker Compose volumes: to mount a directory on any container filesystem path, regardless of whether or not it's declared as a VOLUME.
  • If something is declared as a VOLUME, later RUN instructions can't change that directory tree.
  • If something is declared as a VOLUME, you can never create a derived image that has different contents at that location (for example, you can't create an image derived FROM postgresql with preloaded data).

There's no particular point to declaring VOLUME /tmp (as seems to be common in Java Dockerfiles) or for declaring VOLUME over parts of your application code.

VOLUME declarations are unrelated to an image's WORKDIR.

like image 66
David Maze Avatar answered Sep 07 '25 20:09

David Maze


As illustrated in "Understanding “VOLUME” instruction in DockerFile", a VOLUME in Dockerfile creates a mount point within the container.

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.

This was originally done for different containers to mount and access data from other containers.

See docker run --volumes-from

This is different from data persistence, where you want runtime session data to persist on disk.

For that, see "Manage data in Docker", where you can, at runtime, mount docker volumes, or Host folders (bind mounts), or tmpfs (for writing a large volume of non-persistent state data in the host system’s memory only, for performance, but without persistence)

Runtime manage data

NGiNX by default won't share data with other containers, so does not declare VOLUME in its Dockerfile.

How about NGiNX ? I see static files are at /usr/share/nginx/html but when I cd to this location from host cli it says directory not found, but when I cd from bash mode when executing container in interactive mode this path is displayed

It is meant to receive data from host through bind mount:

docker run --name mynginx \
  -v /var/www:/usr/share/nginx/html:ro \
  -v /var/nginx/conf:/etc/nginx:ro 
-P -d nginx

Those data are "ro" (read-only) within the container.

/usr/share/nginx/html is a path from within the container, which is why, if you cd to it on the host, you would not find it.

like image 26
VonC Avatar answered Sep 07 '25 19:09

VonC