多阶段构建虽然能够减小镜像体积,但是构建的速度慢了许多。原因在于:一是相比于原先的单阶段构建,多了一些构建步骤;二是缓存失效,多阶段编译之后只保留最终镜像的缓存,中间镜像的缓存丢失。其中缓存失效的问题在CI环境中尤为显著。

加快多阶段构建的措施有两项:并行构建和保留缓存

并行构建

从Docker 18.09开始引入了并行构建,启用方法有两种:

  1. 临时启用:设置环境变量DOCKER_BUILDKIT=1

原构建命令: docker build -f Dockerfile -t test_name .

增加DOCKER_BUILDKIT=1后的命令: DOCKER_BUILDKIT=1 docker build -f Dockerfile -t test_name .

  1. 默认启用:在/etc/docker/daemon.json中设置{ "features": { "buidkit": true }}

保留缓存

不仅保留最终镜像的缓存,还保留中间镜像的缓存。

docker build有两个与缓存相关的参数:--cache-fromBUILDKIT_INLINE_CACHE=1--cache-from表示可以指定镜像作为缓存源,可以指定多个镜像,指定后会从镜像仓库自动拉取本地不存在的镜像。BUILDKIT_INLINE_CACHE=1表示在构建时将缓存的元数据打包到镜像中,使之可以作为缓存源。默认构建的镜像不包含缓存的元数据,不能被--cache-from使用。

例子: dockerfile

1
2
3
4
5
FROM 10.xxx:5000/${NODE_ENV}/node-basic:12.22.0-alpine-backend as build
xxx
FROM 10.xxx:5000/${NODE_ENV}/node-basic:12.22.0-alpine as runtime
xxx
CMD [ "pm2", "start", "pm2.json", "--no-daemon" ]

首先将编译阶段的镜像进行构建和上传:

1
2
3
4
5
docker build --build-arg BUILDKIT_INLINE_CACHE=1 \
--cache-from=10.xxx:5000/${NODE_ENV}/node-basic:12.22.0-alpine-backend \
--target build \
--tag 10.xxx:5000/${NODE_ENV}/node-basic:12.22.0-alpine-backend-build .
docker push 10.xxx:5000/${NODE_ENV}/node-basic:12.22.0-alpine-backend-build

然后将最终阶段利用前一阶段和当前阶段的缓存进行构建:

1
2
3
4
5
docker build --build-arg BUILDKIT_INLINE_CACHE=1 \
--cache-from=10.xxx:5000/${NODE_ENV}/node-basic:12.22.0-alpine-backend-build \
--cache-from=10.xxx:5000/${NODE_ENV}/node-basic:12.22.0-alpine-backend \
--tag 10.xxx:5000/${NODE_ENV}/node-basic:12.22.0-alpine-backend .
docker push 10.xxx:5000/${NODE_ENV}/node-basic:12.22.0-alpine-backend

github: https://github.com/moby/moby/issues/34715