使用 dive 工具解读镜像每一层变更内容

解读

在国内一线互联网公司与金融云厂商的面试中,面试官抛出“用 dive 看镜像每层改了什么”并不是想听你背命令,而是考察三条线:

  1. 你是否真的把镜像当成“分层文件系统”来理解,而不是“黑箱压缩包”;
  2. 你是否具备生产级镜像瘦身与漏洞溯源的排查思路;
  3. 你是否能把 dive 的输出翻译成可落地的优化方案(减少层、合并命令、换基础镜像、剔除非必要文件)。
    因此,回答必须展示“命令 + 逐层解读 + 优化结论”的完整闭环,并主动暴露国内镜像源、CI 缓存、安全合规等真实痛点。

知识点

  • OCI 镜像规范:layer tar + manifest + config json 的关系,layer 的“增量化”本质。
  • dive 核心指标:Current Layer Size、Potential wasted space、Efficiency score。
  • 关键快捷键:Tab 切换 Layer/Files 面板,Ctrl+U 过滤仅显示新增,Ctrl+D 显示删除。
  • 国内加速:dive 默认拉镜像走 docker daemon,需提前配置 --registry-mirrordocker pull --platform 解决墙外慢的问题。
  • 安全红线:若某层出现 /.ssh/authorized_keys、/etc/passwd 新增用户、/root/.bash_history,需立即标记为敏感泄漏风险
  • CI 集成:在 GitLab-CI 中可设 dive --ci --lowestEfficiency 95 --highestWastedBytes 50MB,MR 阶段自动拒绝“肥胖”镜像。

答案

“我习惯在 Build 节点上先拉起 dive,命令如下:
dive 公司-harbor.xxx.com/app/api:20230608-1415-sha256
进入 TUI 后,第一步看左侧 Layer 列表,按 Space 把层按大小排序,一眼定位最大层。
第二步按 Tab 切到右侧文件树,用 Ctrl+U 只看新增,发现第 17 层把 /tmp/gcc-11.2.0.tar.xz(148 MB)写进去了,而 Dockerfile 里只在下一层做了 rm,导致‘白占’空间。
第三步切回 Layer 面板,选中第 17 层按 Enter,dive 底部会显示该层命令是‘ADD gcc.tar.xz /tmp’,结合 Efficiency 只有 62%,明确判定为经典“添加即删除”浪费
第四步给出优化:把 ADD 与 tar -xf && rm 合并成一条 RUN,并使用多阶段构建把编译依赖留在 builder 阶段,最终镜像从 387 MB 降到 119 MB,Efficiency 提升到 97%,同时CVE 扫描时间缩短 40%
如果面试官追问‘怎么在 CI 里强制卡住’,我会把 dive --ci 写进 GitLab-CI 的 sast 阶段,配合 --highestUserWastedPercent 5 做质量门,合并请求一旦超标自动打回。”

拓展思考

  1. 当镜像使用 distrolessstatic 二进制时,dive 会显示“零文件变更”层,此时如何证明该层仍包含运行时依赖的 so 链接?可结合 ldd + docker save + tar -xO 手动解包验证。
  2. 国内金融客户要求离线审计,镜像不能出内网,可把 dive 编译成静态二进制放进堡垒机,通过 docker save 导出 tar 再 dive docker-archive:// 实现完全离线分析。
  3. 对于 Windows 容器(ltsc2019/2022),dive 目前仅支持 linux/amd64,需要先用 docker buildx build --platform linux/amd64 交叉构建模拟层,或改用 microsoft/containerregistry-analysis 工具链,避免“工具盲区”导致误判。