在Docker Compose环境中运行的Node.js应用程序找不到模块。

70

非常抱歉我的问题很新手,但是我今天一直在努力解决这个错误,我有一个Express应用程序,我正在尝试在docker-compose中运行它。我使用了这个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

而这部分是我的docker-compose文件:

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"

当我执行docker-compose up命令时,出现了以下错误:

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...

如果我在后端容器中执行ls -al命令,我将获得我的后端应用程序文件夹内容的完整列表,但似乎无法识别node_modules依赖项。

9个回答

69
如果您的 Dockerfilepackage.json 文件正确无误,但仍存在问题,请注意以下事项:
  1. 确保已重建 Docker 镜像。

  2. 尝试执行以下命令:

docker-compose down -v

然后再使用 docker-compose up 启动容器。

此操作将删除所有卷。


1
这对我在处理节点模块时非常有效。不管怎样,也许你应该强调一下“这将删除所有卷”,因为如果你定义了任何数据库的卷,它也会删除这些卷。 - nickelman
2
这个问题已经让我多次措手不及了。 - Jeremy
我从Docker桌面应用中删除了容器,然后重新创建,它就可以工作了。 - Abishek Kumar
谢谢,伙计!这个问题困扰了我很多次。我一遍又一遍地在谷歌上搜索,结果发现我之前已经看过这个答案了,哈哈。 - Goon Nguyen

58
你需要在容器中安装依赖项,这些依赖项在你的 Dockerfile 中缺失。
一般的方法是创建一个已经了解你的应用程序的 Dockerfile,并将其复制你的 package.json 文件并执行 npm install
这样可以使得后续运行你的应用程序时,容器能找到所有的代码依赖项。
请查看此处的示例: https://nodejs.org/en/docs/guides/nodejs-docker-webapp/ 样本 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" ]

当然,您可能需要调整COPY命令的路径。


32
我遵循了相同的指南,但问题仍然存在。 - jemlifathi
4
实际上,我的WORKDIR包含了所有项目文件,但是当启动应用程序时,它无法从node_modules文件夹中获取依赖项!!! - jemlifathi
@CharlieBrown 为什么你会先感到沮丧,而不是简单地将 Docker-compose.yaml 粘贴作为更新。显然它是这里方程式的一部分... - heisian
非常感谢,这对我的情况很有帮助。 - Jose Antonio
我的依赖项已经安装好了,如果我复制镜像并运行相同的命令,它可以正常工作... - Dominic
显示剩余5条评论

29

当我运行docker-compose up时,我也遇到了相同的问题。

通过运行docker-compose up --build而不是docker-compose up解决了该问题。


2
正是我的问题,因为docker-compose up从未重新运行npm install命令,因此新的包没有被安装。 - zhuber
当我运行这个命令时,我也遇到了同样的问题,但是它解决了我的问题:docker-compose up --build - Mamé

20

npm install添加到Dockerfile后,将node_modules添加到卷中。

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

2
好的解决方案!!!有时候你本地的 node_modules 已经过时了,可以使用这个来覆盖原始的本地 node_modules。 - Luk Aron
这个可行,但只有在这个确切的格式下。 - jscul
第二卷是做什么的? - Ali Sherafat

3
如果您的Dockerfiles和compose文件正确,那么您应该执行这个命令:docker-compose build --no-cache,然后再次执行docker-compose up。这对我解决了问题。

这对我绝对起作用,重置了所有内容,包括文件系统。 - William

3

这种情况发生在我因文件名使用了大写字母。

建议的做法是将文件名改为小写。

删除 dist 文件夹。

再次运行。

npm run start:dev

生成一个新的 dist 文件夹。 再次运行。
docker build -t <name> .

1
这并没有显示任何东西,start:dev 命令是 package.json 脚本中的一个命令,它可以是你在那里声明的任何内容。 - Jeremy
这是我的问题,文件大小写不正确。在 Windows 上本地运行正常,但在 Docker 容器中无法工作。谢谢。 - Epirocks

2
请确保在package.json文件的scripts对象中,npm start命令包含nodemon指令以运行你的应用程序。
例如:如果你的应用程序由server.js文件提供服务。
"scripts": {
    "start": "nodemon server.js",
}

1
我曾经遇到同样的问题,你需要做的是运行 npm i 命令来安装所有依赖项,然后重新构建,问题就会得到解决。

0
一些额外的有用信息。列出在 Docker 镜像中安装的 Node 包。在我的例子中,它们安装在/src目录下。
~]$ 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

列出包含已安装的Node包的Docker镜像中的目录内容。当然,应该有一个node_modules目录。
~]$ 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

如果使用docker run命令从镜像部署容器时,我错误地使用了--volume选项,并将本地Docker主机上的文件挂载到容器中的/src目录。/src目录是包含节点包的目录。这导致返回Error [ERR_MODULE_NOT_FOUND]: Cannot find package 'dotenv' imported from /src/app.js
sudo docker run --volume /path/to/local/directory:/src <your Docker image>

我只需要包含文件名,这样我就不会挂载整个/src目录。

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接