I'd like to mount a whole docker image as a volume in the host. I could run the image, but I don't really need to, I just need the files to be visible as files within a directory/volume/mount point outside of docker.
(To be clear, I don't need to mount a host directory as a volume in a running docker instance which is what docker run -v does; I need the opposite, to mount a directory in the docker image or the whole image as a volume in the host; read-only is okay)
Related
Is it currently possible with docker to do something like this conceptually?
docker run --mount type=xxx,image=imageX,subdir=/somedir,dst=/mnt-here imageY ...
I understand this can be done during at docker build time with COPY --from=...., however, in my use-case it would only really be beneficial if it can be done at container creation time.
The only things it's possible to mount into a container arbitrary host directories, tmpfs directories, and Docker named volumes. You can make a named volume use anything you could mount with the Linux mount(8) command. Potentially you can install additional volume drivers to mount other things. But these are all of the possible options.
None of these options allow you to mount image or container content into a different container. The COPY --from=other-image syntax you suggest is probably the best approach here.
If you really absolutely needed it in a volume, one option is to create a volume yourself, copy the content from the source image, and then mount that into the destination image.
docker volume create some-volume
# Since the volume is empty, mounting it into the container will
# copy the contents from the image into the volume. This only happens
# with native Docker volumes and only if the volume is totally empty.
# Docker will never modify the contents of this volume after this.
# Create an empty temporary container to set up the volume
docker run -v some-volume:/somedir --rm some-image /bin/true
# Now you can mount the volume into the actual container
docker run -v some-volume:/mnt-here ...
We have a system in which the user can start sessions inside a number of docker containers. When they do this their home directory is automatically mounted to the docker container. We can't modify the system which starts the docker containers and mounts the directory.
Our goal is to have one image not automatically mount this container. Is there something that I can do to the image to basically make one directory unmountable?
No. If you can docker run a container, you can always use docker run -v to mount any host directory over any directory, and the original contents of the image will be hidden.
Docker's general model is that the image has somewhat limited powers, but you can specify most things when you start the container. Trying to prevent a volume mount (more frequently asked, trying to force a volume mount) is the opposite of this model; the image has no way to prevent how it will eventually be used.
I'd like to mount a file from a Docker's container to my docker host.
Data volumes is not the solution for me, as these are mounts from the docker host to docker containers, and I need the opposite way around.
Thanks
When docker mounts a volume, it overlays the directory inside the container with that of the volume. There is an exception where it will initialize a named volume with the content of that directory in the image. There's no other built in method to copy files out of the image to the volume.
Therefore, to go the other direction and copy the contents of the image directory out to the host with a host volume, you'll need to add your own copy command inside the container. That can be part of your entrypoint script that runs in the container.
An example of the entrypoint script is the volume caching scripts in my base image. One script moves the files to a cached location inside the image during the build, and a second script copies files from the image cached location to the volume mount in the entrypoint.
Is there any difference between:
Mounting a host directory into a container path (the path is not exposed as a volume), e.g.:
docker run -v /host/directory:/container/directory my_image command_to_run
Dockerfile of my_image does not include VOLUME ["/container/directory"]
Mounting a host directory into a a container path exposed as a volume:
docker run -v /host/directory:/container/directory my_image command_to_run
Dockerfile of my_image includes VOLUME ["/container/directory"]
I know that volume data persists independent of the container life-cycle. However, since I want to work on my local data from within a container, does that make any difference if the mount-point inside the container is a volume?
There is no difference if you mount the path from the host into the container. The filesystem from the host will be mounted over top of that directory inside the container.
The difference between listing the volume and not listing it inside the image is the behavior of docker when you create an image without specifying a volume. When the volume is defined on the image, docker will create an "anonymous" volume you can see with docker volume ls as a long uuid string. These volumes are rarely useful, so I recommend against defining a volume in the image and instead only defining them on your docker run command or docker-compose.yml definition.
Downsides of defining a volume in the image include:
Later lines in the Dockerfile or in descendant Dockerfile's may not be able to change the contents at this location. Docker's behavior with this varies by scenario and version, so for predictability, once a volume is defined in an image, I consider that directory off limits.
Creation of anonymous volumes are difficult to use and are likely to clutter up the filesystem.
I posted a blog on this topic a while back if you're interested in more details.
Let's say that I start a docker container with a bind-mounted local folder:
docker run --rm -v /ux1/dmtest:/data -it ubuntu
Then, locally - not inside the container, I bind-mount a directory from another fs into /ux1/dmtest:
mkdir /ux1/dmtest/bm
mount --bind /ux0/bm /ux1/dmtest/bm
Now, from the container, I see /data/bm/ and I can write content to it, but this content will not be visible on the host on /ux0/bm.
Where is this content stored?
And is there any way to mount additional storage into a running docker container (this workaround clearly doesn't work)?
Mounts done after the fact won't be seen by the container due to mount namespaces that Docker uses. The files will be in the /ux1/dmtest directory that was in place before your second bind mount.
If you do want to use a bind mount, put it in place, and then start the docker daemon, and then your container will see it.