为什么"package-lock.json"会导致"npm install"时d



网上有很多人以不同的方式问同一个问题,但没有明确的答案。有人能理解足够的理解来解释为什么当应用程序中存在文件时package-lock.jsondocker build失败,但在不存在时成功运行?似乎它与npm有关,但尚不清楚。

每个人都说删除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 star here
RUN npm install
COPY . .
RUN npm run build

从你的问题:

注意:npm 安装在我的本地机器上工作正常,只是在 docker 容器中失败

如果您使用的是npm install,则不确定是否具有相同版本的依赖项。

为了拥有一个可重现的环境,并且由于不同版本的依赖项而不会出现意外问题,您宁愿使用npm ci(全新安装):

此命令类似于 npm-install,只是它旨在使用 在测试平台等自动化环境中,连续 集成和部署 - 或您想要的任何情况 确保你正在对依赖项进行全新安装。它可以是 通过跳过某些 NPM 安装,比常规 npm 安装快得多 面向用户的功能。它也比常规安装更严格, 这有助于捕获由 增量安装的大多数 npm 用户的本地环境。

简而言之,使用 npm install 和 npm ci 之间的主要区别 是:

  • 项目必须具有现有的package-lock.jsonnpm-shrinkwrap.json.
  • 如果包锁中的依赖项与package.json中的依赖项不匹配,npm ci将退出并显示错误,而不是更新包锁。
  • npm ci一次只能安装整个项目:不能使用此命令添加单个依赖项。
  • 如果node_modules已经存在,则会在npm ci开始安装之前自动将其删除。
  • 它永远不会写入package.json或任何软件包锁:安装基本上是冻结的。

Fabian Gander的文章进一步阐明了npm installnpm 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 版本,因为当主机上node_modules.中存在时,您没有.dockerignorenode_modules并发出 COPY/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)失败。我不确定为什么这些会导致您发布的特定错误。

如果这些原因可能是问题所在,那么解决问题的正确方法肯定是在您打算将代码交付的同一规范的 docker 容器执行所有 npm 操作(包括您生成和操作package.jsonpackage-lock.json),并找出一种方法将结果从那里提交到源代码管理。这可能会因以下问题而变得复杂:在您推送源代码更改的同一环境中构建node_modules有多个需求(例如,结果需要推送到容器中的构建步骤,或需要安装的 git 钩子)。我还没有看到这个问题的完美解决方案

最新更新