You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker镜像构建缓存未命中问题:CI/CD中如何复用远程镜像层?

问题:复用远程Docker镜像层缓存失败

我正尝试提升CI/CD流程的速度,其中一个步骤是构建Docker镜像。镜像构建完成后我会将其推送到镜像仓库,以便在后续CI/CD迭代中先拉取该镜像,复用Docker构建镜像的层缓存,从而减少构建耗时——按预期,若前面的Dockerfile指令未变更,Docker不应重复执行相同的镜像层构建步骤。

以下是实际测试示例:

目录结构

ls
Dockerfile
somefile.txt

Dockerfile内容

cat Dockerfile
FROM ruby:2.7.4-slim

ENTRYPOINT irb

首次构建

docker build -t my-registry/my-docker-cache .
Sending build context to Docker daemon   2.56kB
Step 1/2 : FROM ruby:2.7.4-slim
 ---> db4073acbaac
Step 2/2 : ENTRYPOINT irb
 ---> Running in 14055ed3e5d1
Removing intermediate container 14055ed3e5d1
 ---> f4f317dde34d
Successfully built f4f317dde34d
Successfully tagged my-registry/my-docker-cache:latest

一切符合预期:无缓存,所有步骤均执行。

本地重复构建

docker build -t my-registry/my-docker-cache .
Sending build context to Docker daemon   2.56kB
Step 1/2 : FROM ruby:2.7.4-slim
 ---> db4073acbaac
Step 2/2 : ENTRYPOINT irb
 ---> Using cache
 ---> f4f317dde34d
Successfully built f4f317dde34d
Successfully tagged my-registry/my-docker-cache:latest

结果符合预期:步骤2显示Using cache,未重复执行。

推送镜像到仓库

docker push my-registry/my-docker-cache
aaf6670012a0: Mounted from previous-image-in-other-experiments 
e21a639a3286: Mounted from previous-image-in-other-experiments
f01aae87d116: Mounted from previous-image-in-other-experiments
04f100f96a69: Mounted from previous-image-in-other-experiments
e1bbcf243d0e: Mounted from previous-image-in-other-experiments
latest: digest: sha256:317cbcbb751fc90e3656818a7942ddd67fb8cb9c24841f57cce272bc47c02ce5 size: 1366

删除本地镜像并拉取远程镜像

docker rmi my-registry/my-docker-cache
Untagged: my-registry/my-docker-cache:latest
Untagged: my-registry/my-docker-cache@sha256:317cbcbb751fc90e3656818a7942ddd67fb8cb9c24841f57cce272bc47c02ce5
Deleted: sha256:f4f317dde34ddba589867c3d81af9cd6fe30732afc0173a53740c271d2b70ed3
docker pull my-registry/my-docker-cache
Using default tag: latest
latest: Pulling from my-docker-cache
eff15d958d66: Already exists 
923e91ae3a1b: Already exists 
2aa5d3a4a151: Already exists 
bc64adf2d0b2: Already exists 
bfc5cca7d80e: Already exists 
Digest: sha256:317cbcbb751fc90e3656818a7942ddd67fb8cb9c24841f57cce272bc47c02ce5
Status: Downloaded newer image for my-registry/my-docker-cache:latest
my-registry/my-docker-cache:latest

再次构建(未复用缓存)

docker build -t my-registry/my-docker-cache .
Sending build context to Docker daemon   2.56kB
Step 1/2 : FROM ruby:2.7.4-slim
 ---> db4073acbaac
Step 2/2 : ENTRYPOINT irb
 ---> Running in b779e2e702bf
Removing intermediate container b779e2e702bf
 ---> 73464e25f559
Successfully built 73464e25f559
Successfully tagged my-registry/my-docker-cache:latest

我原本预期步骤2会显示Using cache并不执行,但实际却重新执行了该步骤。虽然ENTRYPOINT步骤耗时很短,但对于RUN bundle install或RUN apt update; apt install xxx这类耗时步骤,影响会很大。

请问我哪里操作有误?或者该如何实现复用远程镜像层缓存的目标?

附Docker版本信息:

docker version
Client: Docker Engine - Community
 Cloud integration: v1.0.28
 Version:           20.10.17
 API version:       1.41
 Go version:        go1.17.11
 Git commit:        100c701
 Built:             Mon Jun  6 23:02:57 2022
 OS/Arch:           linux/amd64
 Context:           desktop-linux
 Experimental:      true

Server: Docker Desktop 4.11.0 (83626)
 Engine:
  Version:          20.10.17
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.17.11
  Git commit:       a89b842
  Built:            Mon Jun  6 23:01:23 2022
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.6.6
  GitCommit:        10c12954828e7c7c9b6e0ea9b0c02b01407d3ae1
 runc:
  Version:          1.1.2
  GitCommit:        v1.1.2-0-ga916309
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

解决方案

原因分析

Docker默认只会优先使用本地镜像的层缓存,拉取远程镜像后,虽然镜像存在,但Docker不会自动将其作为构建缓存的来源。构建缓存是基于本地镜像的层哈希匹配,远程拉取的镜像对应的构建上下文和层关联信息不会被Docker自动识别为可用缓存。

解决方法

要复用远程镜像的层缓存,需要在docker build命令中添加--cache-from参数,指定远程镜像作为缓存源:

docker build --cache-from my-registry/my-docker-cache -t my-registry/my-docker-cache .

这个参数会告诉Docker:先检查指定的远程(或本地)镜像是否包含可复用的层,只要Dockerfile指令和之前一致,就会直接复用该镜像中的对应层,无需重新构建。

补充说明

  • 在CI/CD流程中,建议先拉取目标镜像(即使不存在也不会报错),再执行带--cache-from的构建命令,确保缓存源存在。
  • 对于多阶段构建,可以为每个阶段分别指定--cache-from,比如--cache-from my-registry/my-image:stage1 --cache-from my-registry/my-image:latest,进一步提升缓存复用率。
  • 如果使用Docker Buildx(推荐在CI/CD中使用),可以通过--cache-to和--cache-from配合,将缓存推送到远程仓库,实现跨环境的缓存共享,命令示例:
    docker buildx build \
      --cache-from type=registry,ref=my-registry/my-docker-cache:cache \
      --cache-to type=registry,ref=my-registry/my-docker-cache:cache,mode=max \
      -t my-registry/my-docker-cache . \
      --push
    

内容的提问来源于stack exchange,提问作者Montells

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 23:40:20