问题描述
网上有很多人以不同的方式问这个问题,但没有明确的答案。有人能充分理解为什么docker build
文件在应用程序中存在时为何package-lock.json
失败,而在不存在时成功运行吗?似乎与npm有关,但不清楚。
Everybody说删除package-lock.json
,但这是有原因的。
注意: npm install
在我的本地计算机上工作正常,只是在Docker容器中失败。
如果我有这个Dockerfile:
# First Stage: Builder
FROM node:13.12.0-alpine AS build
workdir /app
copY package*.json ./
RUN npm install
copY . .
RUN npm run build
运行此:
docker build -t container-tag ./
我明白了:
npm WARN tar ENOENT: no such file or directory,open '/app/node_modules/.staging/eventsource-c2615740/example/index.html'
npm WARN tar ENOENT: no such file or directory,open '/app/node_modules/.staging/eventsource-c2615740/example/sse-client.js'
npm WARN tar ENOENT: no such file or directory,open '/app/node_modules/.staging/react-router-a14663ae/README.md'
但是此Dockerfile将成功运行:
# First Stage: Builder
FROM node:13.12.0-alpine AS build
workdir /app
copY package.json ./ #<-------- note that there is no start here
RUN npm install
copY . .
RUN npm run build
解决方法
根据您的问题:
注意:npm install在我的本地计算机上工作正常,只是在docker容器中失败
如果您使用的是npm install
,则不确定是否具有相同版本的依赖项。
要获得可重现的环境,而不会因依赖关系版本不同而出现意外问题,请使用npm ci
:
此命令与npm-install相似,只不过它是要使用的 在自动化环境(例如测试平台)中,连续 集成和部署–或您要进行的任何情况 确保您正在全新安装依赖项。有可能 通过跳过某些步骤,比常规的npm安装快得多 面向用户的功能。它也比常规安装更严格, 这可以帮助您发现由以下原因引起的错误或不一致之处: 大多数npm用户的增量安装本地环境。
简而言之,使用npm install和npm ci之间的主要区别 是:
- 项目必须具有现有的 package-lock.json 或 npm-shrinkwrap.json 。
- 如果程序包锁中的依赖项与 package.json 中的依赖项不匹配,则 npm ci 会退出并显示错误,而不是更新程序包锁。
- npm ci 一次只能安装整个项目:不能使用此命令添加单个依赖项。
- 如果已经存在 node_modules ,它将在 npm ci 开始安装之前自动删除。
- 它永远不会写入 package.json 或任何软件包锁:安装实际上是冻结的。
Fabian Gander's article进一步说明了npm install
和npm ci
工具,并提供了何时使用每个工具的建议。下表来自该来源:
cases | npm install | npm ci
--------------------------------------|-------------|-------------
needs package.json | no | yes
needs package-lock.json | no | yes
installs from package.json | yes | no
installs from package-lock.json | no | yes
compares both | no | yes
updates loose package versions | yes | no
updates loose dependencies | yes | no
writes to package.json | yes | no
writes to package-lock.json | yes | no
deletes node_modules before install | no | yes
used for installing separate package | yes | no
should be used on build systems / CI | no | yes
can be used for development | yes | yes
reproducible installs | no | yes
这就是为什么提供 package-lock.json 的原因,可用于npm ci
之类的工具。
在具有可复制的环境之后,如果这不能解决您的问题,则需要继续调查,但IMO应该是第一步。
,本地构建成功但 Docker 构建失败的一些原因可能是(按可能性排序)
- 您已经用主机上的
node_modules
文件夹覆盖了node_modules
文件夹的 Alpine Linux 版本,因为您没有.dockerignore
node_modules
并发出了 COPY / 当主机上的node_modules
中存在.
时的 ADD 命令
但是,我无法解释为什么从 COPY 中省略 package-lock.json
会使构建工作。所以问题也可能涉及:
- 当您生成
package-lock.json
时,您在与 Dockerfile 中指定的节点版本不同的节点下本地npm install
-ed - 当您生成
package-lock.json
时,您是在与 Alpine Linux 不同的操作系统下本地构建的 - 当您生成
package-lock.json
时,您在与 Docker 容器不同的 npm 版本下在本地进行了npm install
-ed,它可能对锁文件关系的处理方式不同
所有这些操作都可能导致生成 package-lock.json
,从而导致容器中的 npm install
(更有可能导致 npm ci
)失败。我不确定为什么这些会导致您发布的特定错误。
如果这些原因可能是问题所在,那么解决问题的正确方法肯定是在 inside 内进行所有 npm 操作(包括您对 package.json
和 package-lock.json
的生成和操作) strong> 与您打算在其中传送代码的 docker 容器规格相同,以及 work out a way to commit the results to source control from there。这可能会因一些问题而变得复杂,例如在您推送源代码更改的同一环境中构建您的 node_modules
(例如,其结果需要推送到容器中的构建步骤,或需要安装)。我还没有看到这个问题的完美解决方案