Help us learn about your current experience with the documentation. Take the survey.

使用 Docker 层缓存加速 Docker-in-Docker 构建

  • Tier: Free, Premium, Ultimate
  • Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated

在使用 Docker-in-Docker 时,Docker 每次创建构建都会下载镜像的所有层。 Docker 的较新版本(Docker 1.13 及以上)可以在 docker build 步骤中使用现有镜像作为缓存。 这能显著加快构建过程。

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

要在 Docker 27.0.1 及以上版本中使用 Docker 缓存,请执行以下操作之一:

  • 在 Docker 守护进程配置中启用 containerd 镜像存储。
  • 选择其他构建驱动。

更多信息,请参阅 Cache storage backends

Docker 缓存工作原理

运行 docker build 时,Dockerfile 中的每个命令都会创建一个层。 这些层会被保留为缓存,如果没有变更就可以重用。某一层的变更会导致其后所有层的重新创建。

要指定用作 docker build 命令缓存源的有标签镜像,请使用 --cache-from 参数。 可以通过多个 --cache-from 参数指定多个镜像作为缓存源。

Docker 内联缓存示例

此示例 .gitlab-ci.yml 文件展示了如何使用 inline 缓存后端和默认的 docker build 命令来使用 Docker 缓存。

default:
  image: docker:27.4.1
  services:
    - docker:27.4.1-dind
  before_script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY

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"

build:
  stage: build
  script:
    - docker pull $CI_REGISTRY_IMAGE:latest || true
    - docker build --build-arg BUILDKIT_INLINE_CACHE=1 --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 命令的缓存。 任何与 --cache-from 参数一起使用的镜像都必须先通过 docker pull 拉取,才能用作缓存源。
  2. 第二个命令使用拉取的镜像作为缓存(参见 --cache-from $CI_REGISTRY_IMAGE:latest 参数)构建 Docker 镜像(如果可用),并为其打上标签。--build-arg BUILDKIT_INLINE_CACHE=1 告诉 Docker 使用 内联缓存,将构建缓存嵌入到镜像本身中。
  3. 最后两个命令将标记的 Docker 镜像推送到容器注册表,以便它们也可以用于后续构建的缓存。

Docker 注册表缓存示例

您可以将 Docker 构建直接缓存到注册表中的专用缓存镜像中。

此示例 .gitlab-ci.yml 文件展示了如何使用 docker buildx build 命令和 registry 缓存后端来使用 Docker 缓存。 有关更高级的缓存选项,请参阅 Cache storage backends

default:
  image: docker:27.4.1
  services:
    - docker:27.4.1-dind
  before_script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY

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"

build:
  stage: build
  script:
    - docker context create my-builder
    - docker buildx create my-builder --driver docker-container --use
    - docker buildx build --push -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
      --cache-to type=registry,ref=$CI_REGISTRY_IMAGE/cache-image,mode=max
      --cache-from type=registry,ref=$CI_REGISTRY_IMAGE/cache-image .

build 任务的 script

  1. 创建并配置支持 registry 缓存后端的 docker-container BuildKit 驱动。

  2. 构建并推送 Docker 镜像,使用:

    • --cache-from type=registry,ref=$CI_REGISTRY_IMAGE/cache-image 指定专用缓存镜像。
    • --cache-to type=registry,ref=$CI_REGISTRY_IMAGE/cache-image,mode=max 进行缓存更新,其中 max 模式会缓存中间层。