说明 buildx du 接近 0、prune 后 metadata_v2.db 仍增长时,如何只读取证、判断上游缺陷、灰度替换 builder,并控制缓存、费用和回退风险。
BuildKit prune 后 metadata_v2.db 还在变大怎么处理
先确认磁盘增长是否来自构建缓存元数据库,再用新 builder 灰度接管,避免直接改库造成缓存状态损坏
直接答案:如果 docker buildx du 已接近 0、docker buildx prune --all 也完成,但 BuildKit 容器里的 metadata_v2.db 仍持续增长,不能继续把它当成普通可回收缓存处理。2026 年 10 月 9 日的 BuildKit 上游 Issue #7263 报告了一类已删除缓存记录的内容哈希仍留在元数据库的现象;截至本文核验时 Issue 和修复 PR 仍未形成正式发布结论。先只读取证;磁盘压力可控时等待上游版本,压力不可控时创建新 builder、预热并切换任务,最后再删除旧 builder。
本文适用于 docker-container 驱动或可直接管理的独立 BuildKit。只读检查不会删数据;prune 会让后续构建重新下载或重建缓存,替换 builder 会丢失旧 builder 的本地缓存并增加网络、构建时长和镜像仓库费用。不要在运行中的 BuildKit 上用 bbolt 或其他工具删除数据库键,也不要直接删 metadata_v2.db。
先确认不是普通缓存占用
先查看 builder 名称、驱动、节点状态和版本。把 BUILDER_NAME 替换为实际名称:
docker buildx ls
docker buildx inspect BUILDER_NAME --bootstrap
docker buildx version
docker buildx du --builder BUILDER_NAME --verbose
du 有大量 RECLAIMABLE=true 记录时,优先按官方 GC 或 prune 规则处理;这仍属于正常缓存。若 Total 接近 0,但宿主磁盘没有释放,才继续核对 builder 容器和数据库文件。RECLAIMABLE=false 表示记录仍被组件使用,即使加 --all 也不会删除,不应误判为 #7263。
找出 builder 容器并做只读取证
以下命令只查询容器、挂载和文件大小,不停止服务。先从 inspect 确认节点名称,再替换容器名:
BUILDER_CONTAINER=buildx_buildkit_your-builder0
docker inspect "$BUILDER_CONTAINER" --format '{{.Name}} {{.Image}} {{json .Mounts}}'
docker exec "$BUILDER_CONTAINER" sh -c 'find /var/lib/buildkit -name metadata_v2.db -type f -exec ls -lh {} \;'
docker exec "$BUILDER_CONTAINER" sh -c 'du -sh /var/lib/buildkit 2>/dev/null'
记录数据库文件大小后,在正常构建次数增加、且 buildx du 仍很低的情况下隔一段时间复查。只有“可见缓存低、数据库单向增长、prune 后不回落”同时成立,才与上游现场相符。单次文件很大不能证明同一缺陷:活跃缓存、并发构建、快照目录或日志也会占磁盘。
prune 前先判断停机和成本
没有正在运行的构建、并允许下一次全量重建时,才执行一次受控清理。先保存 du 输出,再执行:
docker buildx prune --builder BUILDER_NAME --all --force
docker buildx du --builder BUILDER_NAME --verbose
官方文档说明,prune 是一次性清理,周期 GC 则按年龄和容量策略运行。prune 成功只说明可回收缓存记录已处理,不保证内部元数据库缩小。清理后立即跑关键生产构建,可能造成下载、CPU 峰值和仓库限流;应在低峰执行并保留足够磁盘余量。
数据库仍增长时,优先替换 builder
当数据库增长已经威胁磁盘,而上游尚无正式修复版本时,最可控的恢复方式是并行创建新 builder。镜像版本必须替换成团队审核过的固定版本,禁止照抄 latest:
docker buildx create \
--name buildkit-replacement \
--driver docker-container \
--driver-opt image=moby/buildkit:APPROVED_VERSION \
--bootstrap
docker buildx inspect buildkit-replacement --bootstrap
docker buildx du --builder buildkit-replacement
先用非生产分支构建,再用相同 Dockerfile、构建参数、平台和缓存导入配置跑一条生产等价构建。验收镜像摘要、启动检查、单元测试和部署前扫描。若依赖远端缓存,明确传入原来的 --cache-from;否则新 builder 的第一次构建会自然变慢。
切换、观察和回退
不要用全局 docker buildx use 作为无人值守 CI 的唯一切换方式。优先在流水线中显式传递 --builder buildkit-replacement,先灰度少量任务。观察构建成功率、耗时、磁盘增长、缓存命中和镜像摘要。
| 结果 | 判断 | 下一步 |
|---|---|---|
| 新 builder 正常,数据库增长合理 | 旧实例状态异常的可能性增加 | 继续灰度,备份配置后退役旧 builder |
| 新 builder 同样快速增长 | 可能命中同一上游缺陷或工作负载特征 | 保留版本、Dockerfile 特征和增长曲线,跟踪 Issue/PR |
| 新 builder 构建结果不一致 | 配置、secret、平台或缓存来源未对齐 | 流水线切回旧 builder,不删除旧实例 |
回退只需把 CI 的 --builder 改回旧名称。确认所有任务稳定迁移、无需旧本地缓存且已保存取证后,才能在维护窗口执行 docker buildx rm OLD_BUILDER。删除 builder 会删除其本地状态,通常无法恢复;如果挂载了外部卷,先按团队备份政策核对。
不要用这些危险做法
- 不要在线编辑 BoltDB 的
_external或其他 bucket;Issue 中的内部键解释不是运维接口。 - 不要因为修复 PR 存在就写成某个版本已经修复;只有合并、发布说明和目标版本验证完成后才能升级结论。
- 不要每天无条件 prune all。这会持续牺牲缓存收益,却可能完全不影响异常元数据。
- 不要在磁盘只剩极少空间时才创建新 builder;新旧实例并存和首次构建都需要额外空间。
相关排障
- BuildKit 取消构建后缓存一直 in use
- buildx prune 后下一次构建缓存全部失效
- Docker no space left on device 排查
- Linux 磁盘满了怎么定位
官方与上游来源
- BuildKit Issue #7263
- Docker Docs:Build garbage collection
- Docker Docs:docker buildx du
- Docker Docs:docker buildx prune
来源核验日期:2026-10-13。黑鲨云不是 Docker 或 BuildKit 官方。本文不声称所有数据库增长都由 #7263 引起,也不承诺某个未发布版本已经修复。本稿未发现需要补充确认的黑鲨云业务事实。

