为啥在 `npm install` 时`package-lock.json` 会导致 docker 容器构建失败?
Posted
技术标签:
【中文标题】为啥在 `npm install` 时`package-lock.json` 会导致 docker 容器构建失败?【英文标题】:Why does `package-lock.json` causes a failure in a docker container build when `npm install`?为什么在 `npm install` 时`package-lock.json` 会导致 docker 容器构建失败? 【发布时间】:2020-12-29 07:23:56 【问题描述】:网上有很多人以不同的方式问同样的问题,但没有明确的答案。任何人都可以理解为什么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
,则不确定是否具有相同版本的依赖项这就是 package-lock.json 的用途,为了拥有可重现的环境,由于版本控制而出现意外问题,您应该改用 npm ci
.如果这不能解决您的问题,您需要继续调查,但 IMO 这应该是第一步。希望对您有所帮助。
有道理 - 我不知道 npm ci
,将了解更多信息 - 非常感谢
【参考方案1】:
根据您的问题:
注意: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 或任何包锁:安装基本上是冻结的。
F*** 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 应该是第一步。
【讨论】:
【参考方案2】:您的本地构建成功但 Docker 构建失败的一些原因可能是(按可能性顺序)
您已经用主机中的node_modules
文件夹覆盖了您的node_modules
文件夹的Alpine Linux 版本,因为您没有.dockerignore
node_modules
并且在node_modules
存在时发出了复制/添加命令在主机上的.
但是,我无法解释为什么从 COPY 中省略 package-lock.json
会使构建工作。所以问题也可能涉及:
package-lock.json
时,您 npm install
-ed 在与 Dockerfile 中指定的不同版本的节点下本地编辑
当您生成 package-lock.json
时,您在与 Alpine Linux 不同的操作系统下本地构建
当您生成 package-lock.json
时,您 npm install
-ed 在与 Docker 容器不同版本的 npm 下本地编辑,它可能对 lockfile 关系的处理方式不同
所有这些操作都可能会导致生成package-lock.json
,这可能会导致容器中的npm install
(更有可能导致npm ci
)失败。我不确定为什么这些会导致您发布的特定错误。
如果这些原因可能是问题所在,那么问题的正确解决方案肯定是进行所有 npm 操作(包括您对 package.json
和 package-lock.json
的生成和操作)内部相同您打算在其中运送代码的 docker 容器的规范,以及 work out a way to commit the results to source control from there。这可能会因诸如在您推送源代码更改的同一环境中需要构建 node_modules
的多个问题而变得复杂(例如,其结果需要推送到容器中的构建步骤,或需要安装的 git 挂钩) .我还没有看到这个问题的完美解决方案
【讨论】:
以上是关于为啥在 `npm install` 时`package-lock.json` 会导致 docker 容器构建失败?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 npm install 在 git bash 上不起作用
为啥我必须运行两次“npm install”才能成功安装我的包
为啥“npm install”会修改 package-lock.json?那为啥要把它提交给git呢?
Centos:$ npm install -g vue-cli module.js:549 为啥任何的npm install均报此错,在window上的是正常