Hasty Briefsbeta

双语

The physics of Docker build caching

5 hours ago
  • Docker 构建缓存涉及三种不同的缓存:层缓存、挂载缓存和镜像存储,它们各自具有不同的生命周期和失效规则。
  • 层缓存在一个阶段内是全有或全无的;一个更改会使该层及其链中所有后续层失效。
  • 挂载缓存(例如包管理器缓存)在构建之间持久存在,并通过保留状态使重新运行更快,但它们不会随层缓存后端一起导出。
  • 导出后端(例如 GHA、registry)有助于在全新的运行器上跳过未更改的层,但如果挂载缓存至关重要,由于导入/导出开销,可能比没有缓存更慢。
  • 持久状态(在作业之间保留缓存)在常见场景(如源代码更改和依赖项更新)中显著优于导出后端。
  • Dockerfile 中的层顺序至关重要:将昂贵且稳定的步骤放在频繁更改的内容之前,以优化缓存。
  • 对于编译语言,挂载缓存的持久性是关键;导出后端无法复制这一点,因此持久构建器状态至关重要。
  • 为了最佳效率,应基于镜像谱系(重用层的构建集合)共享缓存,而不仅仅是基于仓库边界。
  • 缓存随不同的依赖版本增长,而不是构建次数;一些工具链会自动修剪,其他的则需要手动重置密钥。
  • 镜像存储缓存(例如共享的 /var/lib/docker)减少了常见镜像的拉取时间,在扇出模式中尤其有益。
  • 可重现的构建和标签对于避免破坏共享镜像缓存中的去重非常重要。
  • 七条经验法则总结了优化 CI 中 Docker 缓存的关键见解,平衡了层顺序、挂载缓存和分发。