在 Docker 与 Dev Container 里让 Claude Code 走聚合站接口
面向在容器里使用 Claude Code 的开发者,讲清如何把聚合站的接口地址与 API key 注入 Docker 与 Dev Container,并梳理 host 网络、代理、环境变量继承等常见坑。
为什么要让容器内的 Claude Code 走聚合站
很多人本机已经配好了聚合站的 API key,但一旦把开发环境搬进 Docker 或 Dev Container,Claude Code 就“失联”了。原因通常不是工具本身,而是容器是隔离的运行环境:它默认看不到宿主机上的环境变量,也未必能解析宿主机访问聚合站的网络路径。
把这两件事理顺,容器里的 Claude Code 就能和本机一样用同一个 key 调多个模型。下面分三步:注入配置、处理网络、验证。
第一步:确认 Claude Code 读取哪些配置
在动手改容器之前,先在本机确认 Claude Code 当前是怎么拿到接口地址和 key 的。常见来源有两类:
- 环境变量:Claude Code 通常通过环境变量获取 API key 与自定义的 base URL。你需要记下变量名和值,稍后在容器里复现。
- 配置文件:部分设置会写在用户目录下的配置文件中,例如
~/.claude相关的配置。容器里如果以 root 运行,用户目录往往和本机不同。
关键点:在容器里复现的是 同样的变量名和同样的 base URL,而不是“再配一次”。把本机生效的配置值原样搬过去,出错概率最低。
第二步:把地址与 key 注入容器
用环境变量注入
最直接的方式是在 docker run 或 compose 里传环境变量:
docker run:用-e逐个传入,或用--env-file指向一个本地的.env文件。docker compose:在environment:或env_file:下声明。- Dev Container:在
devcontainer.json的containerEnv或remoteEnv中声明。
两者的区别值得记住:containerEnv 在容器创建时写入,remoteEnv 在每次连接时注入到会话里,更适合放会变化的 key。
用密钥文件挂载
如果不想把 key 写进镜像或仓库里的 compose 文件,可以把本地配置文件只读挂载进容器:
- 用
-v /host/path:/container/path:ro把~/.claude或某个.env挂进去。 - 挂载后确认容器内的文件权限可读,尤其是容器里用非 root 用户运行时。
这种方式的好处是 key 只存在于宿主机,容器只是“借用”。
不要在镜像里固化 key
把 key 写进 Dockerfile 或用 ARG 传入后留给镜像层,都会让它进入镜像历史。发布或分享镜像时风险很大。key 只应在运行时注入,不落在镜像里。
第三步:处理网络与代理
这是最常见翻车的地方。容器能读到你配的 base URL 不代表它连得上。
容器不是宿主机
默认 bridge 网络下,容器里的 localhost 指的是容器自己,不是宿主机。如果你配的 base URL 是 http://localhost:xxxx 这种指向本机某个代理或中转的情况,在容器里会直接连不上。
几种应对方式:
- 改用宿主机在容器网络中的可达名。Docker Desktop 上通常是
host.docker.internal;Linux 上可以用--add-host=host.docker.internal:host-gateway显式添加。 - 改用
--network=host让容器共享宿主机的网络命名空间,此时localhost才是宿主机的。 - 如果聚合站的地址本来就是公网域名,那多半不需要走宿主机,容器直接访问即可。
host 网络的取舍
--network=host 简单直接,但有代价:
- 端口不再隔离,容器里监听的端口会直接占用宿主机端口。
- 跨平台不一致:Linux 原生支持,Docker Desktop(macOS/Windows)对 host 网络的支持行为不同,不能假设处处一样。
- 多个容器同时用 host 网络时容易端口冲突。
如果只是为了让 Claude Code 出网,用显式的 host 网关名往往比整个切到 host 网络更可控。
代理相关
如果你的宿主机是通过代理访问外网的,容器不会自动继承代理设置:
- 需要把
HTTPPROXY/HTTPSPROXY/NO_PROXY等变量同样注入容器。 NO_PROXY里要记得放聚合站的域名,避免本可直接访问的请求被绕进代理。- 代理运行在宿主机时,注意容器里的代理地址不能用
localhost,同样要用host.docker.internal之类。
环境变量继承的错觉
很多人以为“我 shell 里 export 了,容器里就有”。实际上:
docker run只传显式-e的变量,不继承当前 shell 的完整环境。- Dev Container 里,
containerEnv和remoteEnv是两套机制,生效时机不同。 - IDE 通过 Dev Container 打开时,最终生效的是你连接会话时注入的变量,可能与容器启动时不一致。
排查时,先在容器里打开终端,确认变量真的存在,再去验证联网。
第四步:在容器内验证
按顺序验证,别一步到位地猜:
- 变量是否到位:在容器 shell 里打印相关环境变量,确认名字和值都对。
- 网络是否可达:用
curl之类的工具请求聚合站的基础地址,确认不是 DNS 或连接被拒。 - Claude Code 是否认到配置:启动 Claude Code,确认它没有再报缺少 key 或连不上 base URL。
如果第 2 步就失败,问题在网络上,先解决 host 网关或代理;如果第 2 步成功但第 3 步失败,多半是变量名或配置文件路径没对上。
关于计费的几点提醒
聚合站按官方价 ×1.3 扣费,用 Base 上的 USDC 充值,无需 KYC。一个 API key 可以调多个模型(Claude、GPT、DeepSeek、Qwen、GLM、Kimi 等),容器里注入的就是这个 key。
如果你也把自己的 key 贡献出来,会按官方价 ×1.1(优质 ×1.2)以 USDC 形式返还。这与容器配置无关,但值得知道资金流向。
小结
让容器里的 Claude Code 走聚合站,本质是两件事:
- 配置注入:用环境变量或只读挂载把 base URL 和 key 带进去,且不写进镜像。
- 网络打通:搞清容器里的
localhost指向谁,需要时用 host 网关名、host 网络或代理变量。
先确认变量,再验证网络,最后跑通工具——这个顺序能省掉大部分来回折腾。