I have the problem with installing node_modules
inside the Docker container and synchronize them with the host. My Docker's version is 18.03.1-ce, build 9ee9f40
and Docker Compose's version is 1.21.2, build a133471
.
My docker-compose.yml
looks like:
# Frontend Container. frontend: build: ./app/frontend volumes: - ./app/frontend:/usr/src/app - frontend-node-modules:/usr/src/app/node_modules ports: - 3000:3000 environment: NODE_ENV: ${ENV} command: npm start # Define all the external volumes. volumes: frontend-node-modules: ~
My Dockerfile
:
# Set the base image. FROM node:10 # Create and define the working directory. RUN mkdir /usr/src/app WORKDIR /usr/src/app # Install the application's dependencies. COPY package.json ./ COPY package-lock.json ./ RUN npm install
The trick with the external volume is described in a lot of blog posts and Stack Overflow answers. For example, this one.
The application works great. The source code is synchronized. The hot reloading works great too.
The only problem that I have is that node_modules
folder is empty on the host. Is it possible to synchronize the node_modules
folder that is inside Docker container with the host?
I've already read these answers:
Unfortunately, they didn't help me a lot. I don't like the first one, because I don't want to run npm install
on my host because of the possible cross-platform issues (e.g. the host is Windows or Mac and the Docker container is Debian 8 or Ubuntu 16.04). The second one is not good for me too, because I'd like to run npm install
in my Dockerfile
instead of running it after the Docker container is started.
Also, I've found this blog post. The author tries to solve the same problem I am faced with. The problem is that node_modules
won't be synchronized because we're just copying them from the Docker container to the host.
I'd like my node_modules
inside the Docker container to be synchronized with the host. Please, take into account that I want:
node_modules
automatically instead of manuallynode_modules
inside the Docker container instead of the hostnode_modules
synchronized with the host (if I install some new package inside the Docker container, it should be synchronized with the host automatically without any manual actions)I need to have node_modules
on the host, because:
node_modules
to be installed locally so that it could have access to the devDependencies
such as eslint
or prettier
. I don't want to install these devDependencies
globally.Thanks in advance.
On Unix systems they are normally placed in /usr/local/lib/node or /usr/local/lib/node_modules when installed globally. If you set the NODE_PATH environment variable to this path, the modules can be found by node.
docker run --network="host" Alternatively you can run a docker container with network settings set to host . Such a container will share the network stack with the docker host and from the container point of view, localhost (or 127.0. 0.1 ) will refer to the docker host.
The dependencies are installed using the default package manager inside the Docker container and the node_modules folder appears in your project. Alternatively, open the embedded Terminal ( ⌥ F12 ) and install the packages you need manually, for example, run npm install --save-dev eslint .
When you first install a package to a Node. js project, npm automatically creates the node_modules folder to store the modules needed for your project and the package-lock. json file that you examined earlier. The node_modules folder contains every installed dependency for your project.
At first, I would like to thank David Maze and trust512 for posting their answers. Unfortunately, they didn't help me to solve my problem.
I would like to post my answer to this question.
My docker-compose.yml
:
--- # Define Docker Compose version. version: "3" # Define all the containers. services: # Frontend Container. frontend: build: ./app/frontend volumes: - ./app/frontend:/usr/src/app ports: - 3000:3000 environment: NODE_ENV: development command: /usr/src/app/entrypoint.sh
My Dockerfile
:
# Set the base image. FROM node:10 # Create and define the node_modules's cache directory. RUN mkdir /usr/src/cache WORKDIR /usr/src/cache # Install the application's dependencies into the node_modules's cache directory. COPY package.json ./ COPY package-lock.json ./ RUN npm install # Create and define the application's working directory. RUN mkdir /usr/src/app WORKDIR /usr/src/app
And last but not least entrypoint.sh
:
#!/bin/bash cp -r /usr/src/cache/node_modules/. /usr/src/app/node_modules/ exec npm start
The trickiest part here is to install the node_modules
into the node_module
's cache directory (/usr/src/cache
) which is defined in our Dockerfile
. After that, entrypoint.sh
will move the node_modules
from the cache directory (/usr/src/cache
) to our application directory (/usr/src/app
). Thanks to this the entire node_modules
directory will appear on our host machine.
Looking at my question above I wanted:
- to install
node_modules
automatically instead of manually- to install
node_modules
inside the Docker container instead of the host- to have
node_modules
synchronized with the host (if I install some new package inside the Docker container, it should be synchronized with the host automatically without any manual actions
The first thing is done: node_modules
are installed automatically. The second thing is done too: node_modules
are installed inside the Docker container (so, there will be no cross-platform issues). And the third thing is done too: node_modules
that were installed inside the Docker container will be visible on our host machine and they will be synchronized! If we install some new package inside the Docker container, it will be synchronized with our host machine at once.
The important thing to note: truly speaking, the new package installed inside the Docker container, will appear in /usr/src/app/node_modules
. As this directory is synchronized with our host machine, this new package will appear on our host machine's node_modules
directory too. But the /usr/src/cache/node_modules
will have the old build at this point (without this new package). Anyway, it is not a problem for us. During next docker-compose up --build
(--build
is required) the Docker will re-install the node_modules
(because package.json
was changed) and the entrypoint.sh
file will move them to our /usr/src/app/node_modules
.
You should take into account one more important thing. If you git pull
the code from the remote repository or git checkout your-teammate-branch
when Docker is running, there may be some new packages added to the package.json
file. In this case, you should stop the Docker with CTRL + C
and up it again with docker-compose up --build
(--build
is required). If your containers are running as a daemon, you should just execute docker-compose stop
to stop the containers and up it again with docker-compose up --build
(--build
is required).
If you have any questions, please let me know in the comments.
Hope this helps.
Having run into this issue and finding the accepted answer pretty slow to copy all node_modules
to the host in every container run, I managed to solve it by installing the dependencies in the container, mirror the host volume, and skip installing again if a node_modules
folder is present:
Dockerfile:
FROM node:12-alpine WORKDIR /usr/src/app CMD [ -d "node_modules" ] && npm run start || npm ci && npm run start
docker-compose.yml:
version: '3.8' services: service-1: build: ./ volumes: - ./:/usr/src/app
When you need to reinstall the dependencies just delete node_modules
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With