Dockerizing 一个 NodeJS 应用程序:package.json 在本地可以正常工作,但不能在容器内工作
Posted
技术标签:
【中文标题】Dockerizing 一个 NodeJS 应用程序:package.json 在本地可以正常工作,但不能在容器内工作【英文标题】:Dockerizing a NodeJS app: package.json works fine locally but not inside container 【发布时间】:2020-06-10 21:59:45 【问题描述】:这是我的 Node 应用程序的package.json
:
"name": "my-graphql-app",
"version": "1.0.0",
"description": "My Node GraphQL APP",
"private": true,
"license": "UNLICENSED",
"scripts":
"start": "npm run run:watch",
"build": "webpack",
"build:watch": "webpack --watch",
"run": "node ./dist/app.js",
"run:watch": "nodemon ./dist/app.js"
,
"dependencies":
"@babel/core": "^7.8.4",
"@babel/polyfill": "^7.8.3",
"@babel/preset-env": "^7.8.4",
"apollo-server-express": "^2.10.1",
"babel-loader": "^8.0.6",
"body-parser": "^1.19.0",
"cors": "^2.8.5",
"express": "^4.17.1",
"graphql": "^14.6.0",
"mysql2": "^2.1.0",
"nodemon": "^2.0.2",
"npm-run-all": "^4.1.5",
"sequelize": "^5.21.5",
"webpack-cli": "^3.3.11"
,
"devDependencies":
"webpack": "^4.41.6",
"webpack-node-externals": "^1.7.2"
当我在本地机器上运行 npm install
和 npm start
时,这一切正常(如果有问题,我在 Mac OS Catalina 10.15.3 上运行它)。我的本地节点版本是v11.10.1
。
试图让同一个 Node 应用程序在 docker 容器中运行,我快疯了。我做了很多不同的尝试,调整了package.json
和Dockerfile
,但我总是会遇到一些 npm 安装错误或导入错误。
我正在尝试使用 docker-compose up --build
启动容器(我也有一个 MySQL 容器)。
这是我的Dockerfile
:
FROM node:12
EXPOSE 5000
WORKDIR /graphql_api
COPY package.json .
RUN npm install
COPY . /graphql_api
CMD npm start
这是我的docker-compose.yml
:
version: '3'
services:
database:
image: mysql:5.7
environment:
- 'MYSQL_ROOT_PASSWORD=pwd'
- 'MYSQL_DATABASE=testdb'
- 'MYSQL_USER=user'
- 'MYSQL_PASSWORD=pwd'
volumes:
- ./db:/docker-entrypoint-initdb.d
restart: always
ports:
- 8006:3306
graphql_api:
build: ./graphql_api
container_name: graphql_api
restart: always
volumes:
- ./graphql_api:/graphql_api
- /graphql_api/node_modules
ports:
- "5000:5000"
depends_on:
- database
(顺便说一句,MySQL 容器启动得非常好,并且数据库本身已使用我在 init.sql
文件中定义的所有表正确初始化。)
一旦构建过程到达RUN npm install
点,我总是会收到以下警告:
npm WARN deprecated core-js@2.6.11: core-js@<3 is no longer maintained and not recommended for usage due to the number of issues. Please, upgrade your dependencies to the actual version of core-js@3.
然后我收到一堆这样的消息
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@~2.1.2 (node_modules/chokidar/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.1.2: wanted "os":"darwin","arch":"any" (current: "os":"linux","arch":"x64")
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^1.2.7 (node_modules/watchpack/node_modules/chokidar/node_modules/fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.11: wanted "os":"darwin","arch":"any" (current: "os":"linux","arch":"x64")
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: abbrev@1.1.1 (node_modules/watchpack/node_modules/fsevents/node_modules/abbrev):
npm WARN enoent SKIPPING OPTIONAL DEPENDENCY: ENOENT: no such file or directory, rename '/graphql_api/node_modules/watchpack/node_modules/fsevents/node_modules/abbrev' -> '/graphql_api/node_modules/watchpack/node_modules/fsevents/node_modules/.abbrev.DELETE'
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: ansi-regex@2.1.1 (node_modules/watchpack/node_modules/fsevents/node_modules/ansi-regex):
(我没有全部复制粘贴,因为真的很多。)
在那之后我得到了消息
added 785 packages from 486 contributors and audited 8930 packages in 26.85s
这让我觉得 npm install
确实有一些效果,尽管之前的消息。
但是,当构建过程到达CMD npm start
时,会发生这种情况:
graphql_api | > my-graphql-app@1.0.0 start /graphql_api
graphql_api | > npm-run-all --parallel build:watch run:watch
graphql_api |
graphql_api | sh: 1: npm-run-all: not found
graphql_api | npm ERR! code ELIFECYCLE
graphql_api | npm ERR! syscall spawn
graphql_api | npm ERR! file sh
graphql_api | npm ERR! errno ENOENT
graphql_api | npm ERR! my-graphql-app@1.0.0 start: `npm-run-all --parallel build:watch run:watch`
graphql_api | npm ERR! spawn ENOENT
graphql_api | npm ERR!
graphql_api | npm ERR! Failed at the my-graphql-app@1.0.0 start script.
graphql_api | npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
我也尝试从node:11
映像而不是node:12
映像开始构建容器,以匹配我在本地安装的Node 版本,但结果是一样的。
我真的很茫然:在谷歌搜索并查看其他 *** 答案后,我尝试改变很多东西(例如,在 pacakge.json
中添加的 "private": true
来自我在此处找到的类似答案问题)但我仍然无法让这个容器运行。
【问题讨论】:
您是否有一个.dockerignore
文件可以将主机的node_modules
树保留在图像之外?
另外,您显示的第二组消息看起来像 Docker Compose 输出;您可以在问题中包含您的docker-compose.yml
文件的相关片段吗? (您是否使用 volumes:
绑定挂载覆盖了 Dockerfile 中的所有工作?)
@DavidMaze 我没有.dockerignore
文件,只有.gitignore
文件。是的,你是对的,我确实通过docker-compose
启动了容器,所以现在我将编辑问题以将我的docker-compose.yml
包含在问题中。抱歉,我忘记了那部分。
删除volumes:
对您的graphql_api
容器有帮助吗?这就是将主机 (MacOS) node_modules
目录注入到您的 (Linux) 容器中。
sh: 1: npm-run-all: not found
... 所以node_modules/.bin
不包含在路径变量中(不应该发生,因为它是通过 npm 启动的),模块没有安装(不太可能基于您的日志输出)或 node_modules 文件夹丢失,如***.com/questions/30043872/… 中的测试,您可以将package.json
中的npm start
脚本更改为ls -la node_modules
之类的东西,以确认它不是空的,出于各种原因......跨度>
【参考方案1】:
根据您的错误消息,缺少 npm-run-all 包。在 dockerfile 中,在“npm install”行之前(全局)安装这个包,然后重试。
希望对你有帮助!
【讨论】:
This :npm-run-all
不是 Node 或 npm
的核心部分。您应该将此添加到您的devDependencies
。至于所有可选的依赖警告;这是因为您正在构建一个 Docker 容器,即 Linux。您在 Mac 上看不到这些警告,因为它们是 Mac 需要补偿 Linux 默认具有的功能的软件包,因此它们不是可选的。
事实并非如此。 npm-run-all
包含在我的 package.json
中。此外,正如我在评论中所写,我已将 RUN ls -la node_modules
放在我的 Dockerfile 中,就在 CMD npm start
之前,我确实看到了所有包的列表,包括 npm-run-all
。
@mrodo 你在 node_modules 中看到的是本地安装的包。你需要RUN npm install -g npm-run-all && npm install
。似乎是其中一个库导致了这种情况。【参考方案2】:
您可以尝试将 ./node_modules/.bin/
添加到 dockerfile 中的 PATH 中。这很可能是 npm-run-all 所在的位置。
【讨论】:
【参考方案3】:如果您从 ./graphql_api/node_modules/.bin/ 执行命令,则 npm-run-all 将起作用。
那么在这里你会有两个选择。
-
您可以将 /graphql_api/node_modules/.bin/ 导出到 Dockerfile 中的 PATH 环境变量,如下所示;
ENV PATH="/graphql_api/node_modules/.bin/:$PATH"
您可以通过执行命令npm i -g npm-run-all
将npm-run-all 安装为全局。
请查看我在查看下面提到的问题时发现的这个特定问题。 https://github.com/mysticatea/npm-run-all/issues/96
【讨论】:
【参考方案4】:唯一的方法是将 /graphql_api/node_modules/.bin/ 导出到 PATH。位置可以防止这些影响
【讨论】:
以上是关于Dockerizing 一个 NodeJS 应用程序:package.json 在本地可以正常工作,但不能在容器内工作的主要内容,如果未能解决你的问题,请参考以下文章
使用 Postgresql 对 Spring Boot 应用程序进行 Dockerizing
Dockerizing React App:应用程序在容器内启动,但无法从暴露的端口访问
在单存储库中使用 Lerna 对多个 Node 应用程序进行 Dockerizing