Golo Roden
Golo Roden

Reputation: 150654

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

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?

Upvotes: 418

Views: 218566

Answers (13)

Phil
Phil

Reputation: 71

Docker recently added watch. It allows for directories to be ignored or excluded.

Say you wanted to exclude node_modules directory, you'd do:

services:
  web:
    build: .
    command: npm start
    develop:
      watch:
        - action: sync
          path: ./web
          target: /src/web
          ignore:
            - node_modules/
        - action: rebuild
          path: package.json

Then start the container with:

docker compose watch

You can read more about it in the docs

Upvotes: 7

Caleb Santos
Caleb Santos

Reputation: 89

For a file, an env file specifically, that must exist inside the project, I used this solution:

    volumes:
      - ./empty.env:/app/.env

Where "empty.env" is just an empty file. It helped me to use the same branch in different environments, inside and outside the container.

Upvotes: -1

zilexa
zilexa

Reputation: 21

This works for me Manjaro Linux, Docker Compose yml has v2.4 at the top since thats the last non-swarm version. I want to make sure that my snapshots folder on my host is excluded in the docker container. I do not have volumes section in my docker-compose, keeping it simple:

version: "2.4"    
services:
  filerun:
    volumes:
      - $DATAPOOL/users:/user-files
      - /user-files/snapshots/

On my host, the folder users/snapshots remains untouched. Within the container, the folder user-files/snapshots is just an empty folder.

Upvotes: 2

Thiago Santa Clara
Thiago Santa Clara

Reputation: 49

I found this link which saved me: Working with docker bind mounts and node_modules.
This working solution will create a "exclude" named volume in docker volumes manager. The volume name "exclude" is arbitrary, so you can use a custom name for the volume intead exclude.

services:
    node:
        command: nodemon index.js
        volumes:
            - ./:/usr/local/app/
            # the volume above prevents our host system's node_modules to be mounted
            - exclude:/usr/local/app/node_modules/

volumes:
    exclude:

You can see more infos about volumes in Official docs - Use a volume with docker compose

Upvotes: 4

squid_ink
squid_ink

Reputation: 561

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.

Upvotes: 56

Emmario Delar
Emmario Delar

Reputation: 19

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

Upvotes: -1

Daenor
Daenor

Reputation: 161

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.

Upvotes: 16

DS.
DS.

Reputation: 24110

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.

Upvotes: 24

holdbar
holdbar

Reputation: 81

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/

Upvotes: 8

Frank Wong
Frank Wong

Reputation: 1826

To exclude a file, use the following

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

Upvotes: 30

Nate T
Nate T

Reputation: 2908

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.

Upvotes: 202

kernix
kernix

Reputation: 8490

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.

Upvotes: 658

Adrian Mouat
Adrian Mouat

Reputation: 46500

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.

Upvotes: 14

Related Questions