多架构镜像的体积优化
因为 bazel 用的多,然后也深入阅读并贡献过 rules_oci,所以我对镜像结构和内容的异常会比较敏感。
其实是在弄 sourcemap-less grafana
的时候发现的。
grafana 的镜像当中有前端部分也有后端部分,后端是 go 二进制。我当时在看 blobs 列表的时候就发现不对,有三个蛮大的 blob 的 size 一致。然后就去看了下内容,是前端构建产物。
于是我提了这个 issue grafana/grafana#83079。
其实三份前端产物都是一模一样的,那么为什么他们会成为三个 blobs 没有复用呢(如果使用 rules_oci 这完全是不可思议的)。
原因蛮有意思的。
文件确实一样,都是 Dockerfile 当中使用 COPY --from
或者 ADD
从同一个前端构建源拿到的。但是他们的时间不一致。然后所有目录/文件的时间都记录在了 tar 当中,所以 sha256 不一致。
由于多架构的构建速度不一致,ADD
进去的时间不一致,导致父目录时间不一致。
当 buildkit 将 tar 内容写入 /path/to/target,会隐式得导致这个目录 mtime 发生变化(这并不是 buildkit 期望的,但是确实发生了)。
为了避免这个问题,可以使用 buildkit >= 13.0,使用 SOURCE_DATE_EPOCH 对新的 layer 的 mtime 进行统一修改(虽然这会导致 tar 的 mtime 丢失,但是是目前唯一的解法)
我提了一个 issue 在 moby/moby#47438
多架构镜像的体积优化
https://hunsh.net/20240505/多架构镜像的体积优化/