BuildKit proxy network 中 curl 正常、pip 或 Node.js 证书校验失败时,判断信任链差异并用 secret 安全传入企业 CA。
BuildKit 开启 --proxy-network 后,如果 curl 能访问 HTTPS,而 pip 报 CERTIFICATE_VERIFY_FAILED、Node.js 报 UNABLE_TO_VERIFY_LEAF_SIGNATURE,不要先关闭 TLS 校验。这通常说明代理根证书只进入了系统证书包,但 Python 的 certifi 或 Node.js 的内置根证书没有使用同一条信任链。先确认错误只发生在 BuildKit 构建步骤,再把受控 CA 显式交给对应工具。
本文适用于企业 HTTPS 检查代理和自建 BuildKit。只读检查不会改数据。把 CA 写入镜像会改变最终镜像信任范围;把证书当普通构建参数可能进入镜像历史。默认选择是用 BuildKit secret 临时挂载 CA,并仅在需要联网的 RUN 步骤设置变量。不要使用 --trusted-host、NODE_TLS_REJECT_UNAUTHORIZED=0 或关闭证书校验。
先证明不是 DNS、代理地址或系统证书包故障
先查看构建器和失败步骤。下面命令只读;把 YOUR_BUILDER 换成真实名称。日志可能含私有仓库域名和代理地址,分享前先脱敏。
docker buildx ls
docker buildx inspect YOUR_BUILDER --bootstrap
docker buildx build --progress=plain --no-cache .
在同一个构建阶段分别测试系统工具、Python 和 Node.js。只有镜像原本已经包含这些工具时才执行,不要为了诊断改动生产镜像。
RUN curl -fsSI https://pypi.org/simple/
RUN python -c "import urllib.request; urllib.request.urlopen('https://pypi.org/simple/', timeout=10)"
RUN node -e "require('https').get('https://registry.npmjs.org/',r=>console.log(r.statusCode)).on('error',e=>{console.error(e);process.exit(1)})"
若 curl、wget 或 git 成功,而 Python/Node.js 单独失败,才符合本问题。若三者都失败,先检查代理地址、DNS、宿主机 CA 和 BuildKit 网络;若只有私有镜像仓库失败,应配置 BuildKit 的 registry CA,而不是修改 pip 或 Node.js。
| 结果 | 判断 | 下一步 |
|---|---|---|
| curl 成功,pip/Node 失败 | 工具未使用系统信任链 | 显式指定 CA 文件 |
| 所有 HTTPS 都失败 | 代理、DNS 或系统 CA 问题 | 先修构建器基础网络 |
| 只有 registry push/pull 失败 | BuildKit registry CA 范围 | 配置 buildkitd.toml 的 registry 证书 |
| 关闭代理后成功 | 企业代理信任链未完整配置 | 向网络管理员索取正式根 CA |
用 secret 临时传入 CA
先从企业网络或安全管理员取得正式 PEM 根证书,保存为工作目录外的 company-root-ca.pem。不要从浏览器报错页随意导出未知证书。下面构建命令只把文件作为 secret 交给构建步骤,通常不会把内容写入镜像历史。
docker buildx build --secret id=proxy_ca,src=/SAFE/PATH/company-root-ca.pem --progress=plain --load -t YOUR_IMAGE:test .
Dockerfile 中把 secret 挂载到临时路径,并在同一个 RUN 内为 Python 与 Node.js 指向该文件。不同基础镜像的系统证书路径不同,因此这里不覆盖系统证书包。
# syntax=docker/dockerfile:1
RUN --mount=type=secret,id=proxy_ca,target=/run/secrets/proxy-ca.pem \
SSL_CERT_FILE=/run/secrets/proxy-ca.pem \
REQUESTS_CA_BUNDLE=/run/secrets/proxy-ca.pem \
PIP_CERT=/run/secrets/proxy-ca.pem \
NODE_EXTRA_CA_CERTS=/run/secrets/proxy-ca.pem \
pip install --no-cache-dir -r requirements.txt && npm ci
NODE_EXTRA_CA_CERTS 是附加信任;Python 相关变量可能把默认 CA 路径替换为指定文件。如果企业 CA 文件不包含公共根证书链,Python 访问公共站点仍会失败。更稳妥的做法是由安全团队提供合并且受控的 CA bundle,或在构建阶段生成临时合并文件,不能把网上下载的证书直接加入信任。
什么时候应配置 registry CA
如果失败发生在 BuildKit 拉取基础镜像或推送镜像,而不是 Dockerfile 内的 pip/npm,应在 buildkitd.toml 为对应 registry 配置 CA。Docker 官方说明,自定义配置通过 docker buildx create --buildkitd-config 传入,证书会复制进 BuildKit 容器。该配置只解决指定镜像仓库信任,不会自动解决应用工具自己的证书库。
费用、停机和数据风险
证书排查本身通常没有单独云费用,但无缓存重建会消耗构建机 CPU、网络流量和私有仓库存储。重建 builder 会丢失该 builder 的本地缓存,不能在高峰直接删除。改变最终镜像的系统信任库会扩大所有运行时进程的信任范围,因此默认不把企业代理 CA 永久写入运行镜像。
若临时方案失败,删除 Dockerfile 中的变量和 secret 挂载,恢复上一份可构建的 Dockerfile;不要删除现有 builder。若必须新建 builder,先保留旧名称与配置,新 builder 验证通过后再切换 CI。
修复后如何验收
- 在启用 proxy network 的同一 builder 上,curl、pip 和 npm 三类请求都通过。
- 去掉 secret 后构建按预期失败,证明没有把 CA 意外写进基础镜像或缓存层。
docker history --no-trunc YOUR_IMAGE:test不出现证书正文、私密路径或代理凭据。- 镜像内不存在
/run/secrets/proxy-ca.pem,运行容器仍使用原有信任策略。 - 记录 BuildKit 版本与 Issue 状态;上游正式修复发布后先在测试 builder 复核,再移除临时变量。
相关教程
- Docker buildx prune 后构建缓存整体失效排查
- Docker push 等待响应头超时排查
- Docker pull access denied 排查
- Docker Compose 生产部署与验证

