部署 📋 7 个步骤 第 445 / 446 篇

把 MCP 服务器收进一道网关:用 Docker Sandboxes 统一托管凭证与生命周期

与其让每个 Agent 各自配 MCP,不如在宿主机注册一次。Docker Sandboxes 的 MCP 网关把凭证与生命周期收在宿主机,沙箱内的 Agent 只见一个端点。本教程按 sbx mcp add 与 ls、静态暴露、密钥占位符与 SSRF 取舍的顺序,把这道网关跑通。

2026.09.18· 20 分钟阅读· 约 2378 字· 🐳 Docker Sandboxes / 🔌 MCP 网关

用编码智能体的人都遇到过同一摊乱账:每台机器、每个 Agent 各自配一份 MCP 配置,密钥散落在十几个文件里,谁装过哪个服务器没人记得住,某个同事离职之后他配的那批连接还留在共享环境里。Docker Sandboxes 给出的解法是把 MCP 变成宿主机上的一项注册:你在外面注册一次,沙箱里的 Agent 只看到一个统一的网关端点,凭证由宿主机管、生命周期由宿主机管。

🐳 本教程适合:在多台机器或团队共享环境里跑编码 Agent 的工程同学。需要已登录 sbx,并安装了受支持的 Agent 集成(Claude Code、Codex、Devin、Gemini、Kiro、OpenCode 之一)。

网关模式和「每个 Agent 自己配」差在哪

这两种做法看起来只是配置文件放在哪儿,实际上管的东西完全不同:

维度直接给 Agent 配 MCP宿主机 MCP 网关
生效范围只对这一家 Agent 的客户端生效注册在宿主机,可被多个沙箱复用
凭证位置散落在各家客户端的配置与凭证库里集中托管,沙箱内不接触原始密钥
加载方式每家各配一遍创建沙箱时显式指定要暴露哪个
更新逐个改配置改一处注册,运行中的沙箱可用 load 加载

一个常见误会:这套东西和 Docker Desktop 的 MCP Toolkit 不是同一套。用 sbx mcp 不需要装 MCP Toolkit,两者的服务器设置也不共享。照着 Toolkit 的文档来配 Sandboxes,会一直配不通。

Step 1:先确认前置条件

1 登录 + 至少要有一家能开机即配 MCP 的 Agent
# 登录(网关注册与密钥都挂在你的账号下)
sbx login

# 确认可用的 Agent 集成(会随版本扩展,以官方文档为准)
#   Claude Code / Codex / Devin / Gemini / Kiro / OpenCode

# 如果注册的服务器是走 OCI 包的本地 stdio 服务器,
# 宿主机还需要装好并运行 Docker
🔧 关键前提是「Agent 能在启动时被配置 MCP」。这类集成会把沙箱的网关端点写进 Agent 自己的 MCP 配置,所以只有支持启动期注入 MCP 的 Agent 才能用;纯手动配 MCP 的产品不在此列。

Step 2:在宿主机注册一个 MCP 服务器

2 注册和「挂给沙箱」是两件事
# 注册一个远端 MCP 服务器
sbx mcp add notion --url https://mcp.notion.com/mcp

# 需要 OAuth 的服务器,注册时会先弹一次授权流程
# 授权结果存在宿主机,注册本身不会把服务器挂到任何沙箱上

# 再注册一个
sbx mcp add linear --url https://mcp.linear.app/mcp

名字只能用字母、数字、点、连字符和下划线。要特别注意 --url 后面接的东西决定了它在哪里跑:

--url 指向服务器在哪运行
远端端点地址远端运行,沙箱网关去连它
元数据地址(配合 --local)宿主机用 Docker 拉起 OCI 镜像
显式命令(配合 --command)宿主机上作为 stdio 服务器运行
📌 记住这句话:本地 stdio 服务器跑在宿主机上,不在沙箱里。沙箱内的 Agent 只连网关。想明白这一点,后面看到「为什么沙箱里没有这个进程」就不会困惑了。

Step 3:确认注册结果

3 列出来看一眼类型
sbx mcp ls

# 输出形如:
# NAME     TYPE     URL/COMMAND
# notion   remote   https://mcp.notion.com/mcp
# linear   remote   https://mcp.linear.app/mcp

注册成功不等于连得通。sbx mcp ls 只说明宿主机记下了这条定义;远端服务器是否可达、OAuth 是否还有效,要等沙箱真的去连的时候才知道。遇到工具数为零的情况,先怀疑凭证过期,而不是先怀疑 Agent 不会用工具。

Step 4:起沙箱并暴露服务器

4 静态指定,或给运行中的沙箱按需加载
# 创建沙箱时静态指定要暴露的服务器
sbx run claude --name mcp-demo --static-mcp notion

# 沙箱起来时会带一个 MCP 网关,并预加载 notion
# 同一个注册可以给多个沙箱复用

# 已经跑着的沙箱,按需再挂一个
sbx mcp load linear
🧩 静态和动态的取舍很清楚:固定要用的才用 --static-mcp,让每次新建沙箱都一致;临时排查或按任务切换的用 load。全都堆在静态列表里,等于把网关变成了原先那种「什么都挂着」的配置。

Step 5:自定义请求头,密钥不进注册文件

5 占位符留在配置里,真值进宿主机凭证库
# 注册时用 ${...} 占位符,不要把真密钥写进去
sbx mcp add acme --url https://mcp.acme.com/mcp   --header 'Authorization: Bearer ${api-key}'   --header 'Accept: application/json, text/event-stream'

# 真值存进宿主机的凭证存储(会交互式提示你输入)
sbx secret set mcp:acme:api-key

# 沙箱连接时,网关读取密钥并在请求头里替换占位符
🔐 每个头名只能用一次,需要多个头就重复写 --header。这个设计的好处是注册记录可以安全地进版本库或团队共享:里面只有占位符,没有真密钥。密钥交接变成了「谁需要谁来 set 一次」。

Step 6:把本地 stdio 服务器也纳进来

6 元数据地址与显式命令两种写法
# 写法一:元数据地址 + --local
#   指向 registry 条目 / server.json / server.yaml,
#   sbx 会解析出镜像并在宿主机上用 Docker 跑起来
sbx mcp add my-tool --local --url https://example.com/server.json

# 写法二:显式命令,直接作为 stdio 服务器在宿主机运行
sbx mcp add my-tool --command docker run -i --rm my/mcp-server

--local --url 的场景下宿主机必须有可用的 Docker;--command docker ... 同理。如果只是把 CI 里跑 Agent 的容器搬过来,却没在宿主侧准备 Docker,这一步会卡住,而报错往往不会直白地说「你缺 Docker」。

Step 7:SSRF 检查与它的逃生门

7 默认拦内网,跳过得非常谨慎

如果 --url 的主机名解析到内网、回环、链路本地或云元数据地址,注册仍会成功,但会给你一条警告。OAuth 元数据发现同样会屏蔽这些地址,包括重定向目标。要连可信的内部服务器,才用逃生门:

# 仅在你完全信任该 MCP 主机、OAuth 提供方
# 以及所有元数据重定向目标时才加这个开关
sbx mcp add internal-tool --url https://internal.corp/mcp --skip-ssrf-check

从不可信 URL 拉取清单,可能暴露内部服务或云元数据端点;DNS 重绑定还可能在检查之后把主机名指向别处。这条开关跳过的是两类检查(MCP URL 与 OAuth 元数据发现),不是一类。不要在「先让它跑起来」的心态下随手加。

两个容易搞混的点,再强调一次

一是位置:本地 stdio 的 MCP 服务器运行在宿主机,沙箱内的 Agent 只是网关的客户端。这解释了为什么在沙箱里 ps 找不到那个进程,也解释了为什么宿主机重启会影响所有沙箱。二是边界:sbx mcp 与 Docker Desktop 的 MCP Toolkit 互不共享设置,别把两边的排错经验互相套用。

顺带提醒一句,远端 MCP 端点如果用了私有地址,跳过检查就意味着宿主机可能被引导去访问不该访问的地方。团队共用一台开发机时,这条尤其要注意——注册是一次性的,影响是持续的。

常见问题速查

现象常见原因处理
沙箱里看不到服务器只注册了,没在启动时暴露加 --static-mcp,或对运行中的沙箱用 mcp load
调用报鉴权失败占位符对应的密钥没设或已过期重新 sbx secret set,并确认 OAuth 仍然有效
注册时提示解析到私有地址命中了内网 / 回环 / 云元数据地址确认可信后再考虑 --skip-ssrf-check
本地服务器起不来宿主机缺少或未启动 Docker装好并运行 Docker 后重试
改了服务器设置但沙箱没变沙箱用的是启动时的静态列表重建沙箱,或用 load 重新加载
照着 MCP Toolkit 文档配不通两套产品不共享设置改用 sbx mcp 系列命令

结语

把 MCP 收进网关,本质上是在重复企业 IT 走过很多遍的那条路:先让每个人自己配,等连接多到没人管得过来,再统一收到一层代理后面。这一层带来的收益很实在——密钥不再散落、服务器有账可查、同一个注册能给多个沙箱复用;代价是多了一个需要在宿主机上活着的组件,以及一个必须自己守住的权限边界。

务实的落地顺序是:先把只读类的服务器收进来,确认网关与密钥替换都跑通;再逐步接入会在外部系统写数据的服务器,并对这类服务器保持每次调用的显式暴露。不要在还没验证密钥替换是否生效的情况下,就把所有服务器一股脑注册进来——那只会把原来散落在配置文件里的风险,搬到一个你还没看懂的组件里。

← 返回教程中心