Add a volume to Docker, but exclude a sub-folder

DockerDockerfile

Docker Problem Overview


Supposed I have a Docker container and a folder on my host /hostFolder. Now if I want to add this folder to the Docker container as a volume, then I can do this either by using ADD in the Dockerfile or mounting it as a volume.

So far, so good.

Now /hostFolder contains a sub-folder, /hostFolder/subFolder.

I want to mount /hostFolder into the Docker container (whether as read-write or read-only does not matter, works both for me), but I do NOT want to have it included /hostFolder/subFolder. I want to exclude this, and I also want the Docker container be able to make changes to this sub-folder, without the consequence of having it changed on the host as well.

Is this possible? If so, how?

Docker Solutions


Solution 1 - Docker

Using docker-compose I'm able to use node_modules locally, but ignore it in the docker container using the following syntax in the docker-compose.yml

volumes:
   - './angularApp:/opt/app'
   - /opt/app/node_modules/

So everything in ./angularApp is mapped to /opt/app and then I create another mount volume /opt/app/node_modules/ which is now empty directory - even if in my local machine ./angularApp/node_modules is not empty.

Solution 2 - Docker

If you want to have subdirectories ignored by docker-compose but persistent, you can do the following in docker-compose.yml:

volumes:
  node_modules:
services:
  server:
    volumes:
      - .:/app
      - node_modules:/app/node_modules

This will mount your current directory as a shared volume, but mount a persistent docker volume in place of your local node_modules directory. This is similar to the answer by @kernix, but this will allow node_modules to persist between docker-compose up runs, which is likely the desired behavior.

Solution 3 - Docker

To exclude a file, use the following

volumes:
   - /hostFolder:/folder
   - /dev/null:/folder/fileToBeExcluded

Solution 4 - Docker

For those trying to get a nice workflow going where node_modules isn't overridden by local this might help.

  1. Change your docker-compose to mount an anonymous persistent volume to node_modules to prevent your local overriding it. This has been outlined in this thread a few times.
services:
  server:
    build: .
    volumes:
      - .:/app
      - /app/node_modules
  1. This is the important bit we were missing. When spinning up your stack use docker-compose -V. Without this if you added a new package and rebuilt your image it would be using the node_modules from your initial docker-compose launch.
    -V, --renew-anon-volumes   Recreate anonymous volumes instead of retrieving
                               data from the previous containers.

Solution 5 - Docker

With the docker command line:

docker run \
    --mount type=bind,src=/hostFolder,dst=/containerFolder \
    --mount type=volume,dst=/containerFolder/subFolder \
    ...other-args...

The -v option may also be used (credit to Bogdan Mart), but --mount is clearer and recommended.

Solution 6 - Docker

First, using the ADD instruction in a Dockerfile is very different from using a volume (either via the -v argument to docker run or the VOLUME instruction in a Dockerfile). The ADD and COPY commands just take a copy of the files at the time docker build is run. These files are not updated until a fresh image is created with the docker build command. By contrast, using a volume is essentially saying "this directory should not be stored in the container image; instead use a directory on the host"; whenever a file inside a volume is changed, both the host and container will see it immediately.

I don't believe you can achieve what you want using volumes, you'll have to rethink your directory structure if you want to do this.

However, it's quite simple to achieve using COPY (which should be preferred to ADD). You can either use a .dockerignore file to exclude the subdirectory, or you could COPY all the files then do a RUN rm bla to remove the subdirectory.

Remember that any files you add to image with COPY or ADD must be inside the build context i.e. in or below the directory you run docker build from.

Solution 7 - Docker

for the people who also had the issue that the node_modules folder would still overwrite from your local system and the other way around

volumes:
  node_modules:
services:
  server:
    volumes:
      - .:/app
      - node_modules:/app/node_modules/
    

This is the solution, With the trailing / after the node_modules being the fix.

Solution 8 - Docker

Looks like the old solution doesn't work anymore(at least for me). Creating an empty folder and mapping target folder to it helped though.

volumes:
   - ./angularApp:/opt/app
   - .empty:/opt/app/node_modules/

Solution 9 - Docker

To exclude a mounted file contained in the volume of your machine, you will have to overwrite it by allocating a volume to this same file. In your config file:

services:
  server:
    build : ./Dockerfile
    volumes:
      - .:/app

An example in you dockerfile:

# Image Location
FROM node:13.12.0-buster
VOLUME /app/you_overwrite_file

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGolo RodenView Question on Stackoverflow
Solution 1 - DockerkernixView Answer on Stackoverflow
Solution 2 - DockerNate TView Answer on Stackoverflow
Solution 3 - DockerFrank WongView Answer on Stackoverflow
Solution 4 - Dockersquid_inkView Answer on Stackoverflow
Solution 5 - DockerDS.View Answer on Stackoverflow
Solution 6 - DockerAdrian MouatView Answer on Stackoverflow
Solution 7 - DockerDaenorView Answer on Stackoverflow
Solution 8 - DockerholdbarView Answer on Stackoverflow
Solution 9 - DockerEmmario DelarView Answer on Stackoverflow