当前位置: 首页 > 知识库问答 >
问题:

为什么“package-lock.json”会导致“npm install”时docker容器构建失败?

戴嘉珍
2023-03-14

网上有很多人以不同的方式问这个问题,但没有明确的答案。有人能充分理解为什么当<code>package-lock.json</code>文件存在于应用程序中时,<code>docker build</code<会失败,但当它不存在时,却能成功运行吗?看起来这与npm有关,但目前尚不清楚。

每个人都说删除< code>package-lock.json,但是它的存在是有原因的。

注意:npm 安装在我的本地机器上工作正常,只是在 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

共有2个答案

公羊绪
2023-03-14

您的本地构建成功但Docker构建失败的一些原因可能是(按可能性顺序)

    < li >您已经用主机上的< code>node_modules文件夹覆盖了Alpine Linux版本的< code>node_modules文件夹,因为您没有< code >。dockerignore < code>node_modules,并在< code > node _ modules 存在于< code >中时发出复制/添加命令。在主机上

但是,我无法解释为什么从 COPY 中省略 package-lock.json 会使构建工作。因此,问题也可能涉及:

  • 当您生成包lock.json时,您npm在本地安装-ed,安装的节点版本与Dockerfile中指定的节点版本不同
  • 当您生成包lock.json时,您在本地构建的操作系统与AlpineLinux
  • 不同
  • 当您生成包lock.json时,您npm在本地安装-ed,安装位置与Docker容器的npm版本不同,它可能对lockfile关系有不同的处理

所有这些操作都可能导致生成 package-lock.json,这可能会导致容器中的 npm 安装(并且更可能导致 npm ci)失败。我不确定为什么这些会导致您发布的特定错误。

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

呼延河
2023-03-14

从你的问题:

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

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

为了拥有一个可复制的环境,而不会因为依赖关系的不同版本而出现意外问题,您最好使用npm-ci(干净安装):

此命令类似于npm-install,不同之处在于它适用于自动化环境,如测试平台、持续集成和部署,或者任何需要确保完全安装依赖项的情况。通过跳过某些面向用户的功能,它可以比常规npm安装快得多。它也比常规安装更严格,这可以帮助捕获大多数npm用户增量安装本地环境引起的错误或不一致。

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

    < li >该项目必须有一个现有的package-lock.json或NPM-shrink wrap . JSON。 < li >如果程序包锁中的依赖项与package.json中的不匹配,npm ci将出错退出,而不是更新程序包锁。 < li>npm ci一次只能安装整个项目:不能使用此命令添加单个依赖项。 < li >如果node_modules已经存在,它将在npm ci开始安装之前被自动删除。 < li >它永远不会写入package.json或任何包锁:安装基本上是冻结的。

Fabian Gander的一篇文章进一步阐明了< code>npm install和< code>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存在的原因,它可用于像< code>npm ci这样的工具。

在拥有可重现的环境后,如果这不能解决您的问题,您需要继续调查,但 IMO 这应该是第一步。

 类似资料:
  • 问题内容: 我最近才升级到 npm @ 5 。我现在有一个 package-lock.json 文件,其中包含 package.json中的 所有内容。我希望当我运行该程序时,将从锁定文件中提取依赖项版本,以确定应该在我的 node_modules 目录中安装什么。奇怪的是,它实际上最终修改并重写了 package-lock.json 文件。 例如,锁定文件的打字稿指定为版本 2.1.6 。然后,

  • 我错过了什么?如何让npm真正尊重我的锁文件?

  • npm@5已经发布,它有一个新的功能文件(在之后),这让我很困惑。我想知道,这个文件有什么效果?

  • 问题内容: 我在后台运行一个容器 它迅速退出。但是,如果我在前台运行,则可以正常运行。我使用检查了日志 没有错误。有任何想法吗? DOCKERFILE start-all.sh 问题答案: 一个Docker容器的主要过程完成后退出。 在这种情况下,它将在脚本结束时退出。我对hadoop不太了解,无法在这种情况下告诉您如何做,但是您需要要么在前台运行某些东西,要么使用诸如runit或supervis

  • 问题内容: 好吧,我试图理解并阅读可能导致它的原因,但我却无法理解: 我的代码中有这个地方: 事实是,当它尝试调用某些方法时,它将引发而不是其他预期的异常(特别是)抛出 。我实际上知道调用了什么方法,所以我直接转到该方法代码,并为应该抛出的行添加了一个块 ,它实际上按预期抛出。然而,当它上升时,以某种方式更改了上面的代码并没有 按预期进行。 是什么原因导致这种行为的?我该如何检查? 问题答案: 通

  • 我在尝试构建最新Spark的干净版本时出现了构建错误。我做了以下工作 1)git克隆https://github.com/apache/spark.git ... 生成失败... [错误]无法执行目标org.apache.maven.plugins:maven-enforcer-plugin:1.4:Enforce(enforce-versions)on project spark-parent2

  • 我一直在阅读docs编写Dockerfiles的最佳实践。我遇到了小错误(IMHO),在进一步阅读后,其含义很清楚: 在RUN语句中单独使用apt-get更新会导致缓存问题和后续apt-get安装指令失败。 我想知道为什么失败。后来解释了他们所说的“失败”是什么意思: 由于apt get更新未运行,您的构建可能会获得过时版本的curl和nginx包。 但是,对于以下内容,我仍然无法理解他们所说的“

  • 问题内容: 我添加了一个构建步骤来执行Python脚本。 在此脚本中,使用lint.Run(.. args)调用pylint来检查代码。 该脚本可以工作,但是最后,构建失败,并显示唯一的错误消息: 有人知道为什么会这样吗? 问题答案: 看来您的pylint执行退出状态为非零(缺少脚本,错误的选项…),也许您在退出脚本时引发了异常或