BuildKit v0.33.0 及以下可被超大 Dockerfile 或 .dockerignore 耗尽内存。本文说明版本确认、升级隔离、验收与回退。
直接结论:如果共享构建机、自建 CI 或远程 Buildx builder 可能接收别人提交的构建上下文,先确认真正运行构建的 BuildKit daemon 版本。上游公告确认 BuildKit v0.33.0 及以下会无大小上限地把 Dockerfile 与 .dockerignore 读入内存,超大文件可让 buildkitd 内存耗尽并退出;修复版本是 v0.33.1+。首选处置是升级,不是给单次 RUN 随意加内存。
下面的版本与状态检查都是只读操作,通常不额外收费,也不会删除镜像、缓存或业务数据。升级或重建 builder 会中断正在运行的构建;新 builder 首次构建可能重新拉镜像和生成缓存,产生网络、存储或云主机费用。操作前先停止接收新任务,等现有流水线结束,并保留旧 builder 的名称、驱动、配置文件和缓存位置。
先判断你的构建入口是否真的受影响
风险对象是解析构建定义的 BuildKit daemon,不是最终生成的应用容器。普通开发机只构建自己维护的仓库,暴露面较小;多人 CI、托管代码提交、远程 builder,以及允许外部仓库触发构建的系统,应优先处理。攻击或误操作的结果是构建守护进程被内存压力终止,同一 daemon 上的其他构建也会中断。
先在发起构建的机器执行以下只读命令,记录当前 builder、驱动和节点状态。不要只看 docker buildx version,它显示的是客户端插件版本,不能单独证明远端 daemon 已修复。
docker buildx ls
docker buildx inspect --bootstrap
在输出中找到当前带星号的 builder,并记录 Driver、节点地址和 BuildKit 版本。若明确显示 v0.33.1 或更高版本,可进入权限与验收检查;显示 v0.33.0 或更低版本,应安排升级。版本缺失时不能直接判定安全,要继续按驱动定位 daemon。
版本看不见时,按 builder 驱动继续取证
docker-container 驱动通常把 BuildKit 运行在名为 buildx_buildkit_... 的容器中。先找容器,再读取进程版本和最近状态;以下命令不会重启容器。
docker ps --filter name=buildx_buildkit --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}'
docker exec <BUILDKIT_CONTAINER> buildkitd --version
把 <BUILDKIT_CONTAINER> 替换成上一条输出的真实容器名。若使用 remote、Kubernetes 或厂商托管驱动,应在对应集群或服务中查 daemon 镜像与版本;本机 Buildx 客户端升级并不会自动升级远端节点。没有管理权限时,把 builder 名称、节点地址、当前版本和公告链接交给平台管理员,不要自行删除远程节点。
为什么限制构建步骤内存不能代替升级
docker buildx build --resource memory=... 限制的是 Linux 上单个构建步骤的资源。此次问题发生在 BuildKit 读取 Dockerfile 或 .dockerignore 时,早于普通 RUN 步骤;因此给某个步骤限内存不能证明 daemon 不会被拖垮。官方公告给出的补丁会拒绝超过 16 MiB 的这两类文件,修复边界在 daemon/前端版本。
.dockerignore 仍然应该保持简短、可审查。它负责在发送上下文前排除依赖目录、构建产物和敏感文件,但不能把“文件本身异常巨大”当作正常优化手段。下面的只读检查用于发现仓库中的异常文件大小;它不会读取文件内容。
wc -c Dockerfile .dockerignore 2>/dev/null
find . -maxdepth 3 -type f \( -name 'Dockerfile*' -o -name '*.dockerignore' \) -printf '%s %p\n' | sort -nr
第二条适用于 GNU find。如果 CI 运行在 macOS 或精简系统,使用仓库管理界面查看文件大小即可。发现接近或超过 16 MiB 的构建定义文件,应先隔离提交并审查来源,不要把它复制到另一台共享 builder 上“复现”。
可升级时:新建修复版 builder,先旁路验证
共享构建机不建议直接覆盖正在工作的 builder。更稳妥的做法是以新名称创建修复版节点,先让一条可信流水线旁路验证。下面示例适用于 Docker Engine 上的 docker-container 驱动;镜像版本应按公告选择 v0.33.1 或更高的已批准版本。
docker buildx create \
--name secure-builder \
--driver docker-container \
--driver-opt image=moby/buildkit:v0.33.1 \
--use --bootstrap
docker buildx inspect secure-builder --bootstrap
创建节点会拉取镜像并占用磁盘,可能产生公网流量费用。验证输出中的 BuildKit 版本后,用一个已知可信的小型仓库执行正常构建;确认镜像产物、缓存导入导出、私有仓库凭据和网络代理都符合原链路。不要在公开文章给出的标签上永久锁死,后续应按官方安全公告继续更新补丁版本。
暂时不能升级时:把临时措施当作止损,不当作修复
官方公告给出的临时方向是只构建可信上下文,并给 buildkitd 设置容器或 cgroup 内存限制。对共享 CI 还应暂停外部 fork、匿名任务和未经审核的远程 Git 上下文,把高风险构建与发布生产镜像的 builder 分开。内存限制只能把故障约束在 daemon 容器内,仍可能导致当前与并行构建失败。
低内存机器还可通过 BuildKit 配置降低并行度,减少正常构建的峰值压力;它同样不能修复超大定义文件漏洞。修改 buildkitd.toml 或容器限制前保存原配置,记录 builder 创建参数,并在低峰重建。若节点承载发布任务,先准备可切回的旧 builder,但旧节点不得重新开放给不可信上下文。
升级后如何验收
- 执行
docker buildx inspect secure-builder --bootstrap,确认实际节点版本为v0.33.1+,不是只升级了 Buildx 客户端。 - 运行一条可信的标准构建,核对退出码、镜像摘要、目标仓库和必要的缓存。
- 观察 builder 容器或节点内存,确认正常构建完成后没有 daemon 重启或 OOM 记录。
- 在代码托管和 CI 权限中确认,未审核用户不能把任意仓库、任意分支或外部 URL 直接交给共享 builder。
- 只在隔离测试节点验证超限文件被拒绝;不要在生产共享 builder 上制造超大文件进行压力测试。
若正常构建失败,先把流水线选择器切回已记录的旧 builder,并保留新节点日志排查代理、凭据、缓存和驱动差异。回退只用于恢复可信构建,不代表漏洞风险消失;旧版本节点必须继续关闭外部输入,直到修复版链路通过验收。
与现有 Docker 排障文章怎么配合
如果 daemon 退出且系统日志出现 OOM killed,继续参考Linux OOM Killer 取证;磁盘或 inode 耗尽应转到Docker no space left on device 排查。清理缓存后所有构建失去命中属于另一条路径,可查看Buildx prune 后缓存失效;企业代理下 pip/Node.js 证书错误则参考BuildKit 代理 TLS 排障。
官方来源
- BuildKit 官方安全公告:超大 Dockerfile 或 .dockerignore 可耗尽内存(2026-10-04 核验)
- Docker 文档:构建上下文与 .dockerignore(2026-10-04 核验)
- Docker 文档:配置 BuildKit 与限制并行度(2026-10-04 核验)
- Docker 文档:buildx build 资源参数及边界(2026-10-04 核验)
常见问题
只升级 Docker Buildx 插件够吗?
不够。Buildx 是发起和管理构建的客户端;必须从当前 builder 节点确认实际 BuildKit daemon 已达到 v0.33.1+。
删除超大 .dockerignore 会不会丢业务数据?
删除或缩短忽略规则本身不会删除工作区文件,但可能让原本被排除的密钥、依赖和构建产物进入上下文。应先审查并用正常的小型规则替换,不要直接清空后提交。
是否必须公开复现漏洞后才算验证成功?
不需要。生产验收以修复版本、可信构建成功、权限边界和 daemon 稳定为准。恶意或超大输入只应在隔离环境验证,避免再次中断共享构建。

