claude-code-docker-devcontainer-setup · ZH · 2026-10-06

在 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 打开时,最终生效的是你连接会话时注入的变量,可能与容器启动时不一致。

排查时,先在容器里打开终端,确认变量真的存在,再去验证联网。

第四步:在容器内验证

按顺序验证,别一步到位地猜:

  1. 变量是否到位:在容器 shell 里打印相关环境变量,确认名字和值都对。
  2. 网络是否可达:用 curl 之类的工具请求聚合站的基础地址,确认不是 DNS 或连接被拒。
  3. 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 网络或代理变量。

先确认变量,再验证网络,最后跑通工具——这个顺序能省掉大部分来回折腾。