使用 Docker 镜像层缓存使 Docker-in-Docker 构建速度更快

使用 Docker-in-Docker 时,每次创建构建时,Docker 都会下载镜像的所有层。最新版本的 Docker(Docker 1.13 及更高版本)可以在 docker build 步骤中使用预先存在的镜像作为缓存,明显加快了构建过程。

在 Docker 27.0.1 及以后版本中,默认的 docker 构建驱动程序仅在启用 containerd 镜像存储时支持缓存后端。

要为 27.0.1 及以后版本的 Docker 使用 Docker 缓存,遵循以下其中之一方法:

  • 在你的 Docker 守护进程中启用 containerd 镜像存储。
  • 选择不同的构建驱动程序。

Docker 缓存工作原理

运行 docker build 时,Dockerfile 中的每个命令都会创建一个镜像层。这些镜像层保留为缓存,如果没有更改,可以重复使用。镜像层的变化会导致所有后续层的重建。

要指定要用作 docker build 命令的缓存源的标签镜像,请使用 --cache-from 参数。可以使用多个 --cache-from 参数将多个镜像指定为缓存源。任何与 --cache-from 参数一起使用的镜像都必须先被拉取(使用 docker pull),才能用作缓存源。

Docker 缓存示例

以下 .gitlab-ci.yml 文件示例展示了如何使用 Docker 缓存:

image: docker:20.10.16

services:
  - docker:20.10.16-dind

variables:
  # Use TLS https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#tls-enabled
  DOCKER_HOST: tcp://docker:2376
  DOCKER_TLS_CERTDIR: "/certs"

before_script:
  - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY

build:
  stage: build
  script:
    - docker pull $CI_REGISTRY_IMAGE:latest || true
    - docker build --cache-from $CI_REGISTRY_IMAGE:latest --tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA --tag $CI_REGISTRY_IMAGE:latest .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
    - docker push $CI_REGISTRY_IMAGE:latest

build 阶段的 script 部分:

  1. 第一个命令尝试从镜像库中拉取镜像,以便它可以用作 docker build 命令的缓存。
  2. 第二个命令通过将拉取的镜像用作缓存(请参阅 --cache-from $CI_REGISTRY_IMAGE:latest 参数)(如果可用)构建 Docker 镜像,并为其创建标签。
  3. 最后两个命令将 Docker 标签镜像推送到容器镜像库,以便它们也可以用作后续构建的缓存。