【发布时间】: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