网上有很多人以不同的方式问这个问题,但没有明确的答案。有人能充分理解为什么当<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
从你的问题:
注意:npm 安装在我的本地机器上工作正常,只是在 docker 容器中失败
如果您使用的是npm install
,则不确定是否具有相同版本的依赖项。
为了拥有一个可复制的环境,而不会因为依赖关系的不同版本而出现意外问题,您最好使用npm-ci
(干净安装):
此命令类似于npm-install,不同之处在于它适用于自动化环境,如测试平台、持续集成和部署,或者任何需要确保完全安装依赖项的情况。通过跳过某些面向用户的功能,它可以比常规npm安装快得多。它也比常规安装更严格,这可以帮助捕获大多数npm用户增量安装本地环境引起的错误或不一致。
简而言之,使用npm install和npm ci的主要区别在于:
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构建失败的一些原因可能是(按可能性顺序)
但是,我无法解释为什么从 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.json
和package-lock.json
),并找到一种将结果从那里提交到源代码控制的方法。这可能会因为一些问题而变得复杂,比如在您推送源代码更改的同一环境中需要构建node_modules
(例如,构建步骤的结果需要推送到容器中,或者需要安装的git钩子)。我还没有看到这个问题的完美解决方案