【问题标题】:Optimizing Azure DevOps docker pipeline using cached layers使用缓存层优化 Azure DevOps docker 管道
【发布时间】:2021-02-14 01:32:11
【问题描述】:

我正在尝试优化我的 azure devops 管道中的构建时间,但我的 dockerfile 中的 npm install 阶段不会缓存。为什么?

这是我的 dockerfile。在复制我的其余源代码之前,我已将 package*.json 文件和 npm install 复制到它自己的层中,因为这是最佳实践,并且应该使 npm install 层在构建之间可缓存。

FROM node:12-alpine3.12 AS builder
WORKDIR /app
ARG VERSION

COPY package.json ./
COPY package-lock.json ./
RUN npm install

COPY . .
RUN npm run build

  ...
FROM node:12-alpine3.12
COPY --from=builder /dist .
  ...

这是我的构建管道。由于 Azure 每次都在一个干净的虚拟机上构建,因此我尝试拉下现有图像以利用以前的构建缓存(参考:How to Enable Docker layer caching in Azure DevOps)。

- script: |
    registry=myregistry.azurecr.io
    image=${registry}/myApp:$(Build.SourceBranchName)

    # Pull in previously built builder image because cache
    docker pull ${image}-builder
    # Build the builder target
    docker build \
      --target builder \
      --cache-from ${image}-builder \
      -t ${image}-builder \
      --build-arg VERSION=$(Build.BuildNumber) \
      -f apps/myApp/Dockerfile .

    # Pull in previously built image because cache
    docker pull ${image}
    docker build \
      --cache-from ${image}-builder \
      --cache-from ${image} \
      -t ${image} \
      --build-arg VERSION=$(Build.BuildNumber) \
      -f apps/myApp/Dockerfile .

    docker push ${image}
    docker push ${image}-builder
  displayName: Build and push an image

如您所见,我已将 Dockerfile 中的每个阶段与管道中各自的阶段分开。一个用于构建“构建器”阶段,另一个用于构建生成的图像。每个阶段的 docker 镜像都被推送到我的容器注册表中。 在重建或 package.json 未更改的构建时,我希望 npm install 层输出 ---> Using cache,但在运行“构建器”阶段时它永远不会这样做。

Step 1/8 : FROM node:12-alpine3.12 AS builder
12-alpine3.12: Pulling from library/node
188c0c94c7c5: Already exists
c4e63f2c1114: Already exists
74bf6ceff101: Already exists
1f6472fc624b: Already exists
Digest: sha256:f2e453020045d7d93790777bc3ce2c992f097ce9a6d577d73490093df93b0702
Status: Downloaded newer image for node:12-alpine3.12
 ---> ccd680d0b809
Step 2/8 : WORKDIR /app
 ---> Using cache
 ---> 9f88e2fda996
Step 3/8 : ARG VERSION
 ---> Using cache
 ---> 707e936abbc5
Step 4/8 : COPY package.json ./
 ---> Using cache
 ---> 034785fd08a7
Step 5/8 : COPY package-lock.json ./
 ---> Using cache
 ---> ab778dbabb01
Step 6/8 : RUN npm install
 ---> Running in df1dc4b5bf91
    ...
Removing intermediate container df1dc4b5bf91
 ---> 4ee43e4f6095
Step 7/8 : COPY . .
 ---> 9ea6540727f2
Step 8/8 : RUN npm run build
 ---> Running in bd65f90191a5

请注意上面的Removing intermediate container df1dc4b5bf91。它可能与问题有关?尽管如此,我确实尝试过docker build --rm=false,但它仍然没有在重建时使用缓存层。 但是,在构建管道的最后阶段时,它确实从缓存中运行:

Step 1/16 : FROM node:12-alpine3.12 AS builder
 ---> ccd680d0b809
Step 2/16 : WORKDIR /app
 ---> Using cache
 ---> 9f88e2fda996
Step 3/16 : ARG VERSION
 ---> Using cache
 ---> 707e936abbc5
Step 4/16 : COPY package.json ./
 ---> Using cache
 ---> 034785fd08a7
Step 5/16 : COPY package-lock.json ./
 ---> Using cache
 ---> ab778dbabb01
Step 6/16 : RUN npm install
 ---> Using cache
 ---> 4ee43e4f6095

我错过了什么?

【问题讨论】:

  • 这是您控制的构建节点还是公共节点?如果它是一个公共节点,您可能不会每次都获得相同的节点 - 因此,它不会缓存 NPM 包。
  • 它是一个公共代理。这就是我引入现有映像的原因,因为我知道我每次都会得到一个干净的 VM。参考:stackoverflow.com/questions/59266670/…

标签: docker azure-devops dockerfile azure-pipelines


【解决方案1】:

解决了!

这里的问题是 Dockerfile 中的 ARG 关键字。它总是会改变,从而创建一个无法缓存的层,从而改变下面其他层的哈希。

来自 Docker 文档:https://docs.docker.com/engine/reference/builder/#understand-how-arg-and-from-interact

ARG 是 Dockerfile 中唯一可以在 FROM 之前的指令

ARG VERSION

FROM node:12-alpine3.12 AS builder
WORKDIR /app

COPY package.json ./
COPY package-lock.json ./
RUN npm install

COPY . .
RUN npm run build

  ...
FROM node:12-alpine3.12
COPY --from=builder /dist .
RUN if [ "x$VERSION" = "x" ] ; then echo "VERSION not set" ; else echo "$VERSION" > ./assets/version.txt ; fi
  ...

通过将ARG放在Dockerfile的最前面,docker build context仍然会接收到它,但它不会变成一个层而破坏缓存。

【讨论】:

  • 您好,感谢您的分享,您可以Accept it as an Answer,它可以帮助遇到相同问题的其他社区成员,我们可以存档此线程,谢谢。
  • 我不太明白您的论点VERSION 是如何使用的?通过阅读文档,在 FROM 之外声明的任何参数都不能在 FROM 内部使用,但可以在 FROM 语句中用作 `FROM alpine:${VERSION}
  • @jonas:我编辑了上面的解决方案,以演示如何在 Dockerfile(脚本的最后一行)中使用 VERSION 参数。 ARG 将成为构建范围内的环境变量。
猜你喜欢
  • 2020-07-15
  • 1970-01-01
  • 1970-01-01
  • 2021-02-26
  • 2022-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多