Docker 构建连不上私有依赖:按这个顺序排查
宿主机能拉取的私有包,在构建里仍可能失败。先确定 builder,再验证网络路径,最后把令牌作为构建密钥挂载。
一个在本机能正常解析的私有包,在构建内却可能以 404 或超时失败,而 Dockerfile 很少是原因。构建步骤运行在另一个网络命名空间里,DNS 视图和凭据存储都与你测试时用的 shell 不同。请按顺序做下面这些检查,遇到第一个失败的就停下,因为后面的检查都假定前面的已经通过。每一步都给出能定论的命令。
先确定 builder,而不是 Dockerfile
BuildKit 可以是本地的、容器化的,也可以运行在另一台机器上,而每一种都有自己的默认网络。先运行 docker buildx ls ,在改动任何东西之前看清带星号的那个节点。一个 docker-container 驱动或云端 builder,并不会因为你在本机敲了命令就共用你笔记本上的私有路由。如果当前 builder 是远程的,剩下每一项检查都必须在该主机上跑,而不是在你的工作站上。
builder 还带着自己的 解析器配置和代理变量。两者都在构建时读取,并不会从启动构建的那个终端继承。
在构建步骤内部证明网络路径
写一个一次性阶段,解析依赖的主机并建立到它的连接。这是唯一能替 builder 而不是替你的 shell 回答问题的测试。
FROM alpine:3.20
RUN apk add --no-cache curl bind-tools && getent hosts registry.example.internal && curl -sS -o /dev/null -w "%{http_code}
" https://registry.example.internal/simple/
用真实构建所用的同一个 builder、同一网络模式和同样的密钥挂载来构建这个文件: docker buildx build --builder remote0 -f Dockerfile.probe --progress=plain .。如果 getent 什么都没打印,问题就在名字解析上,任何凭据都救不了。如果名字能解析但 curl 报告超时,那障碍就是路由或注册表前面的出网策略。
探测一旦有结论就删掉它。它只是诊断阶段,永远不应该被标记或推送。
把凭据挂载进去,而不是复制进去
路径通了以后,下一个失败点就是认证。BuildKit 的密钥挂载会把文件只暴露给一个 RUN 步骤,并且不写进镜像层——这正是依赖工具需要的,也正是镜像不该留下的。
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc npm ci --omit=dev
密钥必须从 Dockerfile 外面提供: docker buildx build --secret id=npmrc,src=/home/me/.npmrc .。文件留在客户端,永远不会进入镜像历史。用 ARG 或 ENV 承载同一个令牌并不能完成这件事,因为两者都会被记录进镜像配置。
非 root 镜像需要自己的目标路径,例如 /home/app/.npmrc 或 pip、Maven、Cargo 对应的文件。挂载目标必须与执行命令的用户匹配,否则工具会报告配置文件缺失,而它其实就在那里。
检查依赖工具在镜像里留下了什么
临时挂载能把凭据挡在镜像层之外,却挡不住工具写下别的东西。包管理器会留下 lock 文件、缓存目录,有时还有解析后的仓库地址。
去读构建完的文件系统,而不是相信 Dockerfile。 docker history --no-trunc image:tag 会列出每一条层命令,而 docker run --rm image:tag sh -c "ls -a /root" 显示有什么留进了运行中的容器。即使文件只是被挂载过,在 npm ci 期间写进日志行的令牌依然算泄露。
也读一读构建日志,因为 --progress=plain 会原样打印命令输出。一旦令牌出现在那里,先轮换它,再让它经由一个工具会安静读取的文件传递。
确认运行时镜像不再需要私有路径
构建和运行中的应用是同一个依赖的两个不同消费者,只有前者需要私有路由。构建完成的镜像应当能在没有构建期凭据的情况下启动、解析运行时依赖并提供服务。
在私有仓库不可达的地方测试它,或者干脆用 --network none 启动容器,确认它没有挂载密钥也能起来。一个只有存在构建密钥才能启动的容器,仍然与构建环境耦合。
如果容器在运行时确实需要这个仓库,那就是另一个访问决策,应该放在编排器的密钥库里,而不是构建里。把两条路径分别写清楚,免得有人想用构建参数去修运行时的拉取。当五项检查全部通过时,最初的症状在每一层上都有了名字,而不是对 Docker 网络的猜测。