7

I have a node project and my docker image already has the dependencies installed.

I want to run docker-compose with my project folder to be in sync with the container's folder so I can edit local files and they should change inside the container.

BUT I want to keep whatever content there was inside image's node_modules folder.

I know this question tells me how to ignore a subfolder when mounting a volume, but that will erase the dependencies that were already installed.

Is there any way to mount my project's folder but keep the container's node_modules subfolder?

gfpacheco
  • 2,831
  • 2
  • 33
  • 50
  • 1
    Does this answer your question? [Add a volume to Docker, but exclude a sub-folder](https://stackoverflow.com/questions/29181032/add-a-volume-to-docker-but-exclude-a-sub-folder) – David Maze Feb 23 '20 at 12:25
  • While there's already a highly-voted version of this question, its answers (use a second anonymous volume) don't actually work well: you can tell Docker that your `node_modules` directory contains user data and it will populate it from the image, once, but refuse to ever update it again. – David Maze Feb 23 '20 at 12:26
  • 1
    That question does not help me, I've used that already, but this time I want not only to prevent my host node_modules to be mounted, but keep whatever is inside the image's node_modules – gfpacheco Feb 23 '20 at 12:51

2 Answers2

0

This solution should work for you :

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

When you first run the project with docker-compose up, the node_modules volume will be created and initialized with the content of the container at /app/node_modules. At subsequent calls, the content of the volume (which already exists) will be preserved.

As explained in the documentation:

If you start a container which creates a new volume, as above, and the container has files or directories in the directory to be mounted (such as /app/ above), the directory’s contents are copied into the volume. The container then mounts and uses the volume, and other containers which use the volume also have access to the pre-populated content.

The content of the node_modules volume can be accessed on your host at /var/lib/docker/volumes/<project>_node_modules/_data/

Mathieu Rollet
  • 2,016
  • 2
  • 18
  • 31
  • After some experiments I can say that would work if the second volume would be higher in the list. Because if we already mounted full /app, than the snippet from documentation would mean that /app/node_modules doesn't exist 'in container' anymore. – bromi Feb 01 '23 at 21:19
-1

Try this

Dockerfile

...
RUN mkdir -p /app/node_modules
VOLUMES /app/node_modules
VOLUMES /app
EXPOSE XX
...

Project structure

project/
|--node_modules/
|----...
|--docker_node_modules/
|----...
|--docker-compose.yml
|--...

Docker run command

docker run --it --rm \
    -p xx:xx \
    -v /host/path/project/docker_node_modules:/app/node_modules \
    -v /host/path/project:/app \
    nodeImageExample \
    commandToStartYourNodeApp
  1. From you host when running npm install, it'll be install under ./node_modules (host)

  2. From container when running npm install (container), it'll be install under /app/node_modules (container) and ./docker_node_modules/ (host)

By doing this you have package from your container saved without affecting your node_modules

J-Jacques M
  • 978
  • 6
  • 16
  • The Dockerfile directive is `VOLUME` (singular) but it's not required here, and I'd suggest just deleting it. (Its only effect is to cause Docker to create an anonymous volume on that directory if there's not an explicit `-v` option already, which usually isn't useful, and it prevents later `RUN` instructions from having an effect.) – David Maze Feb 23 '20 at 12:47
  • I don't see how that will help me keep the content from image's `node_modules` while I run docker-compose. It'll just override that with the content from the host's `docker_node_modules` – gfpacheco Feb 23 '20 at 12:54