简体   繁体   English

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

[英]Why does `package-lock.json` causes a failure in a docker container build when `npm install`?

There are a lot of people online asking this same question in different ways but there is no clear answer.网上有很多人以不同的方式问同样的问题,但没有明确的答案。 Can anybody understand enough to explain why a docker build fails when package-lock.json file exists in the application, but runs successfully when it is not?任何人都可以充分理解为什么当应用程序中存在package-lock.json文件时 docker docker build失败,但当它不存在时成功运行? Seemingly it is related to npm but it is not clear.貌似和npm有关,但不清楚。

Everybody says delete the package-lock.json , but it is there for a reason.每个人都说删除package-lock.json ,但它的存在是有原因的。

Note: npm install works fine on my local machine, just fails in docker container.注意: npm install在我的本地机器上工作正常,只是在 docker 容器中失败。

If I have this Dockerfile:如果我有这个 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

And run this:运行这个:

docker build -t container-tag ./

I get this:我明白了:

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'

But this Dockerfile will run successfully:但是这个 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

From your question:从你的问题:

Note: npm install works fine on my local machine, just fails in docker container注意: npm install 在我的本地机器上工作正常,只是在 docker 容器中失败

If you are using npm install , you are not sure to have the same version of dependencies.如果您使用的是npm install ,则不确定是否具有相同版本的依赖项。

For having a reproducible environment, without unexpected issues because of different version of dependencies, you'd rather use npm ci (clean-install):为了拥有一个可重现的环境,并且由于不同版本的依赖关系而不会出现意外问题,您宁愿使用npm ci (clean-install):

This command is similar to npm-install , except it's meant to be used in automated environments such as test platforms, continuous integration, and deployment – or any situation where you want to make sure you're doing a clean install of your dependencies.此命令与npm-install类似,但它旨在用于自动化环境,例如测试平台、持续集成和部署——或任何您希望确保对依赖项进行全新安装的情况。 It can be significantly faster than a regular npm install by skipping certain user-oriented features.通过跳过某些面向用户的功能,它可以比常规的 npm 安装快得多。 It is also more strict than a regular install, which can help catch errors or inconsistencies caused by the incrementally-installed local environments of most npm users.它也比常规安装更严格,可以帮助捕获大多数 npm 用户增量安装的本地环境导致的错误或不一致。

In short, the main differences between using npm install and npm ci are:简而言之,使用 npm install 和 npm ci 的主要区别是:

  • The project must have an existing package-lock.json or npm-shrinkwrap.json .该项目必须具有现有的package-lock.jsonnpm- shrinkwrap.json 。
  • If dependencies in the package lock do not match those in package.json , npm ci will exit with an error, instead of updating the package lock.如果包锁中的依赖项与package.json中的依赖项不匹配, npm ci将退出并出现错误,而不是更新包锁。
  • npm ci can only install entire projects at a time: individual dependencies cannot be added with this command. npm ci一次只能安装整个项目:无法使用此命令添加单个依赖项。
  • If a node_modules is already present, it will be automatically removed before npm ci begins its install.如果node_modules已经存在,它将在npm ci开始安装之前自动删除。
  • It will never write to package.json or any of the package-locks: installs are essentially frozen.它永远不会写入package.json或任何包锁:安装基本上是冻结的。

A Fabian Gander's article gives further clarification about the npm install and npm ci tools and provides advice on when to use each one. Fabian Gander 的文章进一步阐明了npm installnpm ci工具,并就何时使用每一个工具提供了建议。 The below table is from that source:下表来自该来源:

  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

This is why package-lock.json is there, to be available for tools like npm ci .这就是为什么package-lock.json存在的原因,可用于npm ci之类的工具。

After having a reproducible environment, if this doesn't fix your issue, you need to keep investigating, but IMO it should be the first step.在拥有可重现的环境后,如果这不能解决您的问题,您需要继续调查,但 IMO 这应该是第一步。

Some reasons your local build succeeded but the Docker build failed could have been (in order of likelihood)您的本地构建成功但 Docker 构建失败的一些原因可能是(按可能性顺序)

  • you've overwritten the Alpine Linux version of your node_modules folder with the node_modules folder from your host, because you didn't .dockerignore node_modules and issued a COPY / ADD command when node_modules exists in .您已经使用主机中的node_modules文件夹覆盖了 Alpine Linux 版本的node_modules文件夹,因为您没有.dockerignore node_modules并在node_modules存在于. on the host在主机上

However, I can't explain why omitting the package-lock.json from the COPY would then make the build work.但是,我无法解释为什么从 COPY 中省略package-lock.json会使构建工作。 So the problem could also have involved:所以问题也可能涉及:

  • when you generated your package-lock.json , you npm install -ed locally under a different version of node than specified in your Dockerfile当您生成package-lock.json时,您npm install -ed 在与 Dockerfile 中指定的不同版本的节点下本地
  • when you generated your package-lock.json , you built locally under a different operating system than Alpine Linux当您生成package-lock.json时,您在与 Alpine Linux 不同的操作系统下本地构建
  • when you generated your package-lock.json , you npm install -ed locally under a different version of npm from the Docker container, it may have treated the lockfile relationship differently当你生成你的package-lock.json时,你在本地npm install -ed 在与 Docker 容器不同的 npm 版本下,它可能以不同的方式处理 lockfile 关系

All of these actions potentially will cause a package-lock.json to be generated that may cause an npm install (and more likely cause a npm ci ) in the container to fail.所有这些操作都可能导致生成package-lock.json ,这可能导致容器中的npm install (并且更有可能导致npm ci )失败。 I'm not sure why these would cause the specific errors you posted though.我不确定为什么这些会导致您发布的特定错误。

If these reasons could be the issue, the proper solution to the problem is surely to do all your npm manipulation (including your generation and manipulation of package.json and package-lock.json ) inside the same specification of docker container that you intend to ship the code in, and work out a way to commit the results to source control from there .如果这些原因可能是问题所在,那么问题的正确解决方案肯定是在您打算使用的同一 docker容器规范中进行所有 npm 操作(包括您的package.jsonpackage-lock.json的生成和操作)将代码发送进来,然后想办法将结果从那里提交给源代码控制 This can be complicated by issues like there being several needs to build your node_modules in the same environment you push source-code changes from (for instance a build step whose results need pushing into the container, or a git hook that needs installing).这可能会因诸如在推送源代码更改的同一环境中需要多个构建node_modules等问题而变得复杂(例如,结果需要推送到容器中的构建步骤,或需要安装的 git 挂钩)。 I've not yet seen a perfect solution to this issue我还没有看到这个问题的完美解决方案

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么“npm install”会重写package-lock.json? - Why does “npm install” rewrite package-lock.json? 为什么`npm install`为同一个`package.json`文件生成不同的`package-lock.json`文件? - Why does `npm install` generate different `package-lock.json` files for the same `package.json` file? 为什么“npm install”修改package-lock.json?为什么要把它交给git呢? - Why does “npm install” modify package-lock.json? Why commit it to git then? 为什么“npm install git repo url”会重写package-lock.json? - Why does “npm install git repo url” rewrite package-lock.json? 如果我更改节点版本并安装 npm ,package-lock.json 中的 package 版本是否更改? - If I change the node version and do npm install, does the package versions in package-lock.json change? 当我在不同系统上运行`npm install`时,为什么会得到很大的`package-lock.json`文件 - Why do I get vastly different `package-lock.json` files when I run `npm install` on different systems package-lock.json 在 npm 安装后被重写 - package-lock.json is rewritten after npm install 在 docker 容器中安装依赖项后如何复制回主机 package-lock.json/yarn.lock? - How to copy back to host package-lock.json/yarn.lock after install dependencies inside docker container? NPM:在package-lock.json中更改注册表 - NPM: change registry in package-lock.json npm pack 和缺少 package-lock.json - npm pack and missing package-lock.json
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM