为什么在 docker 中复制项目的其余部分之前先复制 package.json 并安装依赖项?

Why copy package.json and install dependencies before copying the rest of the project within docker?

我看过很多关于如何使用 docker 构建应用程序的教程,大多数时候 Dockerfile 复制 package.json、package-lock.json 然后运行安装,最后复制应用程序的其余部分。

Dockerfile 复制示例 package.json,package-lock.json 在应用程序的其余部分之前

Source

FROM node:12.18.2 as build

ARG REACT_APP_SERVICES_HOST=/services/m

WORKDIR /app

COPY ./package.json /app/package.json
COPY ./package-lock.json /app/package-lock.json

RUN yarn install
COPY . .
RUN yarn build


FROM nginx
COPY ./nginx/nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=build /app/build /usr/share/nginx/html

这让我触发了为什么采用这种方法而不是复制整个应用程序然后 运行 安装。如果不打算复制 node_modules 文件夹,只需将文件夹添加到 .dockerignore 文件即可解决此问题。或者是另外一个问题,按照这个顺序做的时候被阻止了。

Docker 图片由图层组成。我们可以看到层,例如,当我们拉取图像时。如果我们拉取一个镜像,我们可能会看到类似“layer already exists”的消息,说明我们已经下载了这一层,不需要重新下载。

当我们从容器文件构建镜像时,容器文件中的指令 RUNCOPYADD 会创建一个新层。我们的目标是以这样一种方式分层我们的图像 - 从上到下阅读 - 内容更改频率较低。

在我们的应用程序中,最有可能更改的部分是源代码本身。应用程序的依赖项更改频率较低。因此,我们希望将依赖项放在一个单独的层中,这样当我们重建容器并且只有源代码更改时,只能推送源代码中的更改(并因此在我们部署时拉取),从而加快我们的部署时间。

由于 Docker 层缓存,它已完成。如果您 运行 docker build 当复制的文件 none 已更改时,图像层将仅从缓存中读取。如果 COPY 文件已更改,将重建图像中之后 的所有图层。

RUN yarn install 是一个昂贵的操作,我们不希望在项目中的任何随机源文件更改时再次执行它。这样,只有在 package.jsonpackage-lock.json 文件发生变化时才会重新执行。