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 installnpm start 时,这一切正常(如果有问题,我在 Mac OS Catalina 10.15.3 上运行它)。我的本地节点版本是v11.10.1

试图让同一个 Node 应用程序在 docker 容器中运行,我快疯了。我做了很多不同的尝试,调整了package.jsonDockerfile,但我总是会遇到一些 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 &amp;&amp; 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 nestjs 应用程序时出错

Dockerizing React App:应用程序在容器内启动,但无法从暴露的端口访问

在单存储库中使用 Lerna 对多个 Node 应用程序进行 Dockerizing

dockerizing Spring Boot 应用程序错误:错误:无效或损坏的 jarfile /app.jar

Dockerizing springboot应用程序(在容器中)未连接到rabbitmq(在容器中):连接被拒绝