提问者:小点点

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


网上有很多人以不同的方式问这个问题,但没有明确的答案。有人能充分理解为什么当<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个答案

匿名用户

从你的问题:

注意: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 这应该是第一步。

匿名用户

您的本地构建成功但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钩子)。我还没有看到这个问题的完美解决方案