How to mount Docker volume along with subfolders on the host?

Hi,

I do have docker volume called /usr/local/tomcat/webapps and it’s having sub folder inside of it.

I would like to mount /usr/local/tomcat/webapps on host volume (/usr/share/tomcat/webapps) so that application team can check directly on host instead of logging into docker volume.

I got many examples in forums to mount host volumes on docker volumes but not other way.

Can anyone help me how to achieve this?

Hi

Whats wrong with that way?
If you need to provide data from the container on your host system, to mount it (using -v) into a container sounds like the perfect solution?

I’m not sure we 100% understand what you’re saying but I believe what you want to achieve is to give your application team access a specific folder in the container without them having to launch an interactive shell on the conainer.

Personally I would achieve this using a bind mount:

version: "3.8"

services:
  container_name:
    image: alpine:latest
    ## TRUNCATED -##
   volumes:
      - 'volume_name:/path/in/container'

volumes:
  volume_name:
    driver: local
    driver_opts:
      type: 'none'
      o: 'bind'
      device: '/path/on/host'

After this I would make the folder on the host a network share and adjust the permissions accordingly.

Nobody should be logging in to the host unless they are managing containers, and nobody should ever be logging in to the containers.

I’m saying this is the only way, or even the right way, but having just heard the problem, this is my first thought. If it were me, and it was a production environment, then I’d actually be looking at some external/shared storage which is attached to the docker host and then mounted to the container like this.

2 Likes

But you said:
“I would like to mount /usr/local/tomcat/webapps on host volume (/usr/share/tomcat/webapps) so that application team can check directly on host instead of logging into docker volume.”

and now you’re saying:
“Nobody should be logging in to the host unless they are managing containers, and nobody should ever be logging in to the containers.”

why do they need to check the data?
what kind of data is it?
If its logs, then maybe look into elk/splunk.

We have too different users here. @sikotic wrote an answer not the question. :slight_smile:

1 Like

Haha good catch :sweat_smile: didnt see that

No problem.
The fact that you didn’t disagree with my proposed solution makes me feel like maybe I’m actually starting to understand all this :wink:

1 Like

If I get it right, the OP wants a container folder, with preexisting data from the image, to be available on the host.

sikotic’s approach to use a named volume backed by a bind is already the best option there is, but it still has caveats.

Named volumes provide a copy-on-first-use mechanism, where the content of a container folder is copied back into the named volume. Then the named volume will be mounted on top of the container folder, thus making the content inherited by the image invisible.

So whenever you change content in the image path, create a container from it and use an already existing named volume, the container path will use whatever state the volume has. The changes of the images would have never been seen by the container. Unless the volume and its content gets deleted and the container re-created.

Overall depending on the volumes copy-on-first-use mechanism is usually not the most reliable thing to do.

You might want to modify your image, so that the content of the folder is stored in a different folder, then let your entryoint script take care to copy the files to the final location (where you mount the volume) or migrate files or however your conflict resolution strategy will look like.

2 Likes

Thanks for the clear information. Yes, I ma able to view the container content on host by using named volume.

Can you able to provide an example how to use in cli instead of docker compose?

I have used below command and able to see container data in /var/lib/docker/volumes.

May I know what command I need to add in cli if I need to change path in host?

docker run -d --restart=always -p 8182:8182 -v tomcat_webapps:/usr/local/tomcat/webapps -v tomcat_logs:/usr/local/tomcat/logs image

docker run -d \
  -it \
  --name devtest \
  -v /path/on/host:/path/on/container\
  nginx:latest

or

docker run -d \
  -it \
  --name devtest \
  --mount type=bind,source=/path/on/host,target=/path/on/container \
  nginx:latest

Taken from: Use bind mounts | Docker Documentation

Interesting.
I was under the impression that bind mounts didn’t copy data. Are you saying that, if you create a volume which is a bind mount, and then reference it by name in your compose file, it still copies the data?

The Docker run reference | Docker Documentation states the following:

The `nocopy` mode is used to disable automatically copying the requested volume
path in the container to the volume storage location.
For named volumes, `copy` is the default mode. Copy modes are not supported
for bind-mounted volumes.

I am unclear, do I need to set the nocopy option? I originally took this to mean that, because it was a bind-mounted volume, it would not copy the data.
@srinvas, the answer to this will affect the -v command I gave earlier, but not the --mount command.

That’s great. Thank you.

A bind mount as in “-v /host/path:/container/path” indeed does not, but a volume backed by a bind should. If you use the nocopy mode, of course a volume backed by a bind will behave like a normal bind-mount (those not listed in docker volume ls).

1 Like

Great, thanks. I’ll update my compose file.

Just to be sure: the recommendation is to not use “nocopy”, unless you want that behavior!

Just to be clear, part 2: This one is not a volume backed by bind. It is a mount-bind. This will not copy the files from the image path back to a named volume, as there is no named volume involved.

This should be shouted from the mountains. I’ve been searching for this for ages as I can bake my python dependencies into the image and then use this to expose the files locally so neovim can jump to definition for the code that is inside the container. There are so many open issues with this scattered on the internet that I thought there was no way. Thank you!