69

I am sorry for my very newbie question, but I am having a terrible day figuring out this error, I have an Express app and I am trying to run it in docker compose. I've used this Dockerfile:

FROM mhart/alpine-node
RUN mkdir -p /usr/src/app
RUN chmod -R 777 /usr/src/app
WORKDIR /usr/src/app
RUN npm install node-gyp -g
RUN npm install nodemon -g
ENV NODE_ENV development
EXPOSE 3000

And this portion of my docker-compose file:

backend:
    mem_limit: 100m
    build:
      context: .
      dockerfile: dockerfiles/node/Dockerfile
    command: npm start
    depends_on:
      - mongo
      - elasticsearch
    volumes:
      - ./backend/:/usr/src/app
    ports:
      - 3000:3000
    links:
      - "mongo:mongo"
      - "elasticsearch:elasticsearch"

When I do docker-compose up, I get this error:

backend_1        | npm info it worked if it ends with ok
backend_1        | npm info using npm@3.10.10
backend_1        | npm info using node@v6.9.5
backend_1        | npm info lifecycle service-designer@1.0.0~prestart: service-designer@1.0.0
backend_1        | npm info lifecycle service-designer@1.0.0~start: service-designer@1.0.0
backend_1        | 
backend_1        | > service-designer@1.0.0 start /usr/src/app
backend_1        | > nodemon index.js
backend_1        | 
backend_1        | [nodemon] 1.11.0
backend_1        | [nodemon] to restart at any time, enter `rs`
backend_1        | [nodemon] watching: *.*
backend_1        | [nodemon] starting `node index.js`
backend_1        | module.js:471
backend_1        |     throw err;
backend_1        |     ^
backend_1        | 
backend_1        | Error: Cannot find module 'dotenv'
backend_1        |     at Function.Module._resolveFilename (module.js:469:15)
backend_1        |     at Function.Module._load (module.js:417:25)
backend_1        |     at Module.require (module.js:497:17)
backend_1        |     at require (internal/module.js:20:19)
backend_1        |     at Object.<anonymous> (/usr/src/app/index.js:1:63)
backend_1        |     at Module._compile (module.js:570:32)
backend_1        |     at Object.Module._extensions..js (module.js:579:10)
backend_1        |     at Module.load (module.js:487:32)
backend_1        |     at tryModuleLoad (module.js:446:12)
backend_1        |     at Function.Module._load (module.js:438:3)
backend_1        | [nodemon] app crashed - waiting for file changes before starting...

If I do ls -al in the backend container, I get a full list of my backend app folder content, but it sounds like node_modules dependencies are not recognized.

jemlifathi
  • 1,482
  • 5
  • 22
  • 32

9 Answers9

67

If your Dockerfile and package.json files are correct and still have the issue:

  1. Make sure you've rebuilt your container images.

  2. Try

docker-compose down -v

before starting the containers again with docker-compose up.

This removes all volumes.

M3RS
  • 6,720
  • 6
  • 37
  • 47
  • 1
    This worked for me when going back and forth with node modules. Anyhow, maybe you should highlight "This removes all volumes" a bit since it will remove volumes for database as well, if you have any of those defined. – nickelman Aug 13 '20 at 08:20
  • 1
    This has caught me out so many times. – Jeremy Mar 15 '22 at 09:04
  • I deleted the container from docker desktop and recreated it, and it worked. – Abishek Kumar Oct 20 '22 at 14:33
  • Thanks mate, it got me so many times! I searched Google again and again and I found out that I already read this haha – Goon Nguyen May 26 '23 at 11:30
58

You need to install the dependencies in the container, which is missing from your Dockerfile.

The common way is to create a Dockerfile that is already aware of your application, and make it copy your package.json file and perform an npm install.

This allows your container to find all your code dependencies when you later run your application.

See and example here: https://nodejs.org/en/docs/guides/nodejs-docker-webapp/

The sample Dockerfile:

FROM node:boron

# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

# Install app dependencies
COPY package.json /usr/src/app/
RUN npm install

# Bundle app source
COPY . /usr/src/app

EXPOSE 8080
CMD [ "npm", "start" ]

You may need to adapt paths for the COPY command, of course.

CharlieBrown
  • 4,143
  • 23
  • 24
  • 32
    I've followed the same guide, but I still having the same issue – jemlifathi Feb 04 '17 at 12:57
  • Your Dockerfile is missing all the `package.json` stuff, or you didn't paste the full stuff. There's no `npm install` at all in your question, that's why there's nothing in `node_modules`. Double check your paths inside the container, i.e. that your node code is in the same folder as your node_modules. Your code will be mounted with the `volume` in Docker-compose but the dependencies will be there from your `Dockerfile`. – CharlieBrown Feb 04 '17 at 13:12
  • 4
    Actually, my WORKDIR contains all my project files but when launching the app, it is unable to fetch dependencies from node_modules folder !!! – jemlifathi Feb 04 '17 at 13:32
  • `FROM node:boron RUN mkdir -p /usr/src/app WORKDIR /usr/src/app RUN npm install node-gyp -g RUN npm install nodemon -g COPY backend/ /usr/src/app/ RUN npm install ENV NODE_ENV development EXPOSE 3000` Bro, I've tried this configuration, the same error appears every time, when I replace "npm start" by "ls -al" I get all my code and dependencies listed but the dependencies like express, etc. seems to be undefined when running the Node JS app. I really hope you get it! – jemlifathi Feb 04 '17 at 17:13
  • Nope, not the same as in the article. You only COPY (in Dockerfile) the package.json and then you add the volume with the code in your Docker-compose.yaml. – CharlieBrown Feb 04 '17 at 17:17
  • Do you mean this: `FROM node:boron RUN mkdir -p /usr/src/app WORKDIR /usr/src/app RUN npm install node-gyp -g RUN npm install nodemon -g RUN npm install ENV NODE_ENV development EXPOSE 3000` and `backend: mem_limit: 100m build: context: . dockerfile: Dockerfile.node command: npm start depends_on: - mongo - elasticsearch volumes: - ./backend/:/usr/src/app` – jemlifathi Feb 04 '17 at 18:11
  • @CherlieBrown Apparently I encountred the same issue as http://stackoverflow.com/questions/30043872/docker-compose-node-modules-not-present-in-a-volume-after-npm-install-succeeds – jemlifathi Feb 05 '17 at 10:55
  • @CharlieBrown why would you get frustrated first and not simply paste Docker-compose.yaml as an update. Obviously it's a part of the equation here... – heisian Jul 21 '17 at 02:15
  • thank you very much, this was helpful in my case – Jose Antonio Oct 07 '21 at 17:36
  • My dependencies are installed, if I copy the image and run the same command it works fine... – Dominic Dec 22 '21 at 01:46
29

I also had the same issue when I run docker-compose up.

Issue resolved by running docker-compose up --build instead of docker-compose up.

Nishanth Duvva
  • 665
  • 8
  • 18
  • 2
    Exactly my issue, because docker-compose up never rerunned npm install command and therefore new packages weren't installed. – zhuber Aug 26 '21 at 13:22
  • I had also same issue when I run this command it solved my problem ```docker-compose up --build``` – Mamé Jan 23 '22 at 16:11
19

After adding npm install to the Dockerfile, add node_modules to volumes

volumes:
      - ./backend/:/usr/src/app
      - /usr/src/app/node_modules
3

It happened to me because I had the file names in upper case.

what is recommended is rename files to lowercase

delete the dist folder

run again

npm run start:dev

to generate a new dist folder.

again run the

docker build -t <name> .
  • 1
    This doesn't really show anything, the start:dev command is a command from package.json script and that can be whatever you have declared there. – Jeremy Feb 19 '22 at 14:16
  • This was my problem, the files were the wrong case. Worked locally on Windows but not in a docker container. Thanks. – Epirocks Mar 10 '22 at 02:09
3

If your Dockerfiles and compose file are correct then you should do this docker-compose build --no-cache Then you can do docker-compose up again. This resolved the issue for me.

acha jackson
  • 81
  • 1
  • 1
2

Make sure that in package.json in the scripts object the npm start has the nodemon command to run your application

Example: if your application is served by the server.js file

"scripts": {
    "start": "nodemon server.js",
}
LastM4N
  • 1,890
  • 1
  • 16
  • 22
1

I had the same issue, what you need to do is simply run npm i to install all the dependencies and after that rebuild, issue resolved

Daniel
  • 61
  • 2
0

A few additional things I found helpful. List the node packages installed in the Docker image. In my example, they were installed in the /src directory.

~]$ sudo docker run -it --rm <your Docker image> npm list
@johndoe /src
+-- cors@2.8.5
+-- dotenv@16.0.3
+-- express@4.18.2
`-- node-fetch@3.3.1

List the contents of the directory in the Docker image that contains the installed node packages. Of course, there should be a node_modules directory.

~]$ sudo docker run -it --rm test ls -l /src
total 36
drwxr-xr-x   69 root     root          4096 May 22 07:11 node_modules
-rw-r--r--    1 root     root         26405 May 22 07:11 package-lock.json
-rw-r--r--    1 root     root           416 May 22 07:11 package.json

If using the docker run command to deploy a container from the image, I mistakenly used the --volume option and mounted files on my local Docker host to the /src directory in the container. The /src directory was the directory that contained the node packages. This caused Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'dotenv' imported from /src/app.js to be returned for me.

sudo docker run --volume /path/to/local/directory:/src <your Docker image>

I just had to include the file names so that I was not mounting over the entire /src directory.

sudo docker run --volume /path/to/local/file/example.txt:/src/example.txt <your Docker image>
JeremyCanfield
  • 633
  • 11
  • 24