为什么`npm install`时package-lock.json会导致Docker容器构建失败? [英] Why does `package-lock.json` causes a failure in a docker container build when `npm install`?
问题描述
网上有很多人以不同的方式问这个问题,但没有明确的答案.有人能充分理解为什么当 package-lock.json
文件存在于应用程序中时,为什么 docker build
失败,但没有运行时成功运行的原因吗?似乎与npm有关,但不清楚.
所有人说删除 package-lock.json
,但这是有原因的.
注意: npm install
在我的本地计算机上工作正常,只是在Docker容器中失败.
如果我有这个Dockerfile:
#第一阶段:生成器FROM节点:13.12.0-alpine AS buildWORKDIR/appCOPY包* .json ./运行npm安装复制 ..运行npm运行构建
运行此:
docker build -t容器标签./
我明白了:
npm WARN TAR ENOENT:无此类文件或目录,请打开"/app/node_modules/.staging/eventsource-c2615740/example/index.html"npm WARN TAR ENOENT:无此类文件或目录,请打开"/app/node_modules/.staging/eventsource-c2615740/example/sse-client.js"npm WARN TAR ENOENT:没有此类文件或目录,请打开"/app/node_modules/.staging/react-router-a14663ae/README.md"
但是此Dockerfile将成功运行:
#第一阶段:生成器FROM节点:13.12.0-alpine AS buildWORKDIR/appCOPY package.json ./#< --------注意这里没有开始运行npm安装复制 ..运行npm运行构建
来自您的问题:
注意: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 或任何包锁:安装实际上是冻结的.
A Fabian Gander的文章进一步阐明了 npm install
和 npm ci
工具,并提供了有关何时使用每个工具的建议.下表来自该来源:
案例|npm安装|npm ci-------------------------------------- | ------------| -------------需要package.json |没有是的需要package-lock.json |没有是的从package.json安装|是的不从package-lock.json安装|没有是的比较两者|没有是的更新松散的软件包版本|是的不更新松散的依赖关系|是的不写入package.json |是的不写入package-lock.json |是的不在安装前删除node_modules |没有是的用于安装单独的软件包|是的不应该在构建系统/CI上使用|没有是的可用于开发|是的是的可复制的安装|没有是的
这就是为什么 package-lock.json 出现在其中的原因,可用于 npm ci
之类的工具.
具有可复制的环境后,如果这不能解决您的问题,则需要继续调查,但IMO应该是第一步.
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? Seemingly it is related to npm but it is not clear.
Everybody says delete the package-lock.json
, but it is there for a reason.
Note: npm install
works fine on my local machine, just fails in docker container.
If I have this 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:
# 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
From your question:
Note: npm install works fine on my local machine, just fails in docker container
If you are using npm install
, you are not sure to have the same version of dependencies.
For having a reproducible environment, without unexpected issues because of different version of dependencies, you'd rather use npm ci
:
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. It can be significantly faster than a regular npm install by skipping certain user-oriented features. 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.
In short, the main differences between using npm install and npm ci are:
- The project must have an existing package-lock.json or npm-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.
- npm ci can only install entire projects at a time: individual dependencies cannot be added with this command.
- If a node_modules is already present, it will be automatically removed before npm ci begins its install.
- It will never write to package.json or any of the package-locks: installs are essentially frozen.
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. 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
.
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.
这篇关于为什么`npm install`时package-lock.json会导致Docker容器构建失败?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!