“改了一行 Dockerfile,整个 apt/apk 安装又重新下载一遍”是构建慢的常见原因。RUN --mount=type=cache 让包管理器的缓存目录跨构建保留。这篇用 apk 实测:第一次、之后每次各要多久,缓存里的东西会不会进镜像,以及缓存怎么按 id 区分。
[没有缓存挂载] BUST=1:退出码 0,构建用时 181917 ms
BUST=1
Executing ca-certificates-20260413-r0.trigger
OK: 15 MiB in 24 packages
[没有缓存挂载] BUST=2:退出码 0,构建用时 98042 ms
BUST=2
Executing ca-certificates-20260413-r0.trigger
OK: 15 MiB in 24 packages
[没有缓存挂载] BUST=3:退出码 0,构建用时 195787 ms
BUST=3
Executing ca-certificates-20260413-r0.trigger
OK: 15 MiB in 24 packages
[RUN --mount=type=cache,target=/var/cache/apk] BUST=1:退出码 0,构建用时 193675 ms
BUST=1 进入时缓存目录里有 0 个文件
Executing ca-certificates-20260413-r0.trigger
OK: 15 MiB in 24 packages
结束时缓存目录里有 13 个文件,共 4644 KB
[RUN --mount=type=cache,target=/var/cache/apk] BUST=2:退出码 0,构建用时 943 ms
BUST=2 进入时缓存目录里有 13 个文件
Executing ca-certificates-20260413-r0.trigger
OK: 15 MiB in 24 packages
结束时缓存目录里有 13 个文件,共 4644 KB
[RUN --mount=type=cache,target=/var/cache/apk] BUST=3:退出码 0,构建用时 764 ms
BUST=3 进入时缓存目录里有 13 个文件
Executing ca-certificates-20260413-r0.trigger
OK: 15 MiB in 24 packages
结束时缓存目录里有 13 个文件,共 4644 KB缓存挂载不是魔法:缓存为空的那一次构建要照常下载(193.7 秒,这台机器的网络很慢)。之后每次进入这一步时目录里已经有 13 个文件,同一条 apk add 只要 0.94 秒。没有缓存挂载时即使 Dockerfile 只改了一个无关的 ARG 导致这一层重做,每次也要重新下载(98–196 秒)。
从有缓存挂载的镜像启动后 ls /var/cache/apk | wc -l = 0(目录里没有文件) 两个镜像的 Size:没有缓存挂载 27.63 MB;有缓存挂载 23.00 MB
缓存目录只在构建那一步里挂载,构建结束就不在镜像里了:从镜像启动后 /var/cache/apk 是空的。所以缓存不会让镜像变大——也就不需要在 RUN 末尾再 rm -rf 缓存。
第 1 次构建:id=one 里有 0 个文件 | id=two 里有 0 个文件 第 2 次构建:id=one 里有 1 个文件 | id=two 里有 0 个文件
同一个 id 的缓存在构建之间持续累积(第二次构建能看到第一次写进去的文件),不同 id 互不影响。本文每次都显式写了 id;不写时的默认规则我没有测。缓存数据在构建器所在的机器上,CI 里如何持久化,本文没有测。