Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does docker create empty node_modules and how to avoid it?

Tags:

node.js

docker

There are some similar questions but they haven't answered why docker creates the empty node_modules directory in the repo even though the dockerfile is setup to hold node_modules in the container?

I'm interested to know why directory is created on the host empty, give that yarn already installs packages inside the container within node_modules and how to avoid it.

## Dockerfile

FROM node:8.11.4-alpine
RUN apk update && apk add yarn
RUN yarn global add nodemon
WORKDIR /usr/app

COPY package.json yarn.lock /usr/app/
RUN yarn

EXPOSE 3000

## docker-compose.yml

version: "3.2"

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    command: nodemon index.js
    volumes:
      - .:/usr/app
      - /usr/app/node_modules
    ports:
      - "3000:3000"

like image 651
denski Avatar asked Jan 19 '19 17:01

denski


People also ask

Should I put node_modules in Dockerignore?

dockerignore file, then the docker build process would have slowed down due to unnecessary copying of the node_modules , PLUS the image would have been larger. Therefore, the prudent thing is to keep node_modules inside . dockerignore file to achieve more efficiency in the docker build process.

Do I need to push node_modules in production?

No, You don't need to push your node_modules folder to production whether it is a static export or dynamic build. When you export a static build the source file is converted into HTML & js files. So there is no need for node modules on production env.

Should node modules be in docker image?

Basically, you don't want to mix up the node_modules on your host with the node_modules in the container. On macOS and Windows, Docker Desktop bind-mounts your code across the OS barrier, and this can cause problems with binaries you've installed with npm for the host OS, that can't be run in the container OS.


1 Answers

You are right, your image building process is installing the node packages into the node_modules directory in the image. So, after you build your image the image contains node_modules and you can use it to run your application.

You see node_modules on your host machine, because of your volumes setup in your Compose file. There is more to it than you see in the other answer though.

What's happening is that you are mapping .:/usr/app in your first volume definition, which means that you are mapping your current directory on the host to /usr/app in the container.

This will override the /usr/app directory in the image with the current directory on the host. And your host does not have the node_modules directory (unless you installed node_modules on the host, too) and therefore your container will not work with this mapping, beacuse you've overriden /usr/app and there is no node_modules dir in the override. Node will throw an error that it cannot find node modules.

The next volume mapping solves the situation, this is actually a common Node development setup. You create a volume /usr/app/node_modules. Note, that this volume does not have a host part there is no : in the mapping, there is only one directory here. This means that Docker will mount the /usr/app/node_modules directory from the image and add it to the previous mapping where you mapped the host dir to /usr/app.

So in the running container you'll have your source code from the host's current directory PLUS node_modules from the underlying image due to the double mapping.

As a side effect you'll see an empty node_modules directory in your host's current directory.

like image 70
takacsmark Avatar answered Oct 08 '22 10:10

takacsmark