ClaudeMap

·MCP 服务器

2026 年 MCP 服务器容器化部署实战——stdio 与容器常驻的本质矛盾、300+ 签名服务器的 Docker MCP Catalog、docker mcp CLI 与 Gateway(三种 transport / 认证 / 凭据)、Claude Desktop 与 Claude Code 对接、Compose 编排,以及 2026-07-28 无状态化对 K8s 部署的意义。

MCP 服务器 Docker 部署指南:Catalog、Gateway 与 Compose 编排(2026)

把 MCP 服务器装进 Docker 容器,解决的是三件事:安装依赖不再污染本机、server 拿不到你的宿主环境、所有工具调用有一层可审计的网关。Docker 为此提供了三层工具——MCP Catalog(300+ 个签名容器化服务器)、docker mcp CLI(Toolkit)、以及 MCP Gateway(统一运行与管控)。本文基于 2026 年 9 月的 Docker 官方文档与 docker/mcp-gateway 仓库,覆盖从单机 stdio 到 Compose 编排的完整部署路径。

TL;DR

  • stdio 服务器的本质是「client 拉起的子进程」,与容器常驻天生矛盾——MCP Gateway 是官方解法:client → Gateway → 容器化的 server
  • 本机客户端照旧写 mcpServers,只是 command 换成 docker mcp gateway run;容器网络内的客户端则直连 http://gateway:9011/mcp
  • Catalog 里的 server 带 attestation 与签名 SBOM,mcp/ 命名空间镜像默认启用签名验证
  • sse / streaming 模式默认要求 Bearer token(MCP_GATEWAY_AUTH_TOKEN),浏览器 Origin 仅接受 localhost
  • 2026-07-28 规范移除协议级会话后,server 容器天然无状态——K8s 滚动更新不再撕断会话

为什么 stdio MCP 服务器和 Docker「天生不和」

MCP 规范对 stdio 的定义是「经由 client 拉起的子进程的标准流、以换行分隔的消息」——server 的生命周期由 client 掌握。而容器的模型是常驻、独立、由编排器管理。两者拼在一起会出现一连串问题:谁拉起容器?client 退出了容器要不要停?有状态的 server 数据放哪?

Docker 官方对这道题的答案分两条路:

路线 A:Gateway 作为 client 的 stdio 子进程。 架构是 AI Client → MCP Gateway → MCP Servers (Docker Containers)——client 只认识 Gateway 一个进程,Gateway 负责按需把 server 作为容器拉起(「若该服务器未运行则将其作为 Docker 容器启动」)、聚合工具、回传结果。client 侧零改动,容器生命周期由 Gateway 全权管理。

路线 B:Gateway 以 HTTP 常驻。 docker mcp gateway run --transport streaming --port 8080 让 Gateway 变成一个服务多客户端的网络端点——容器网络里的其他服务、CI 任务、团队共享的 server 池都走这条线。

有状态 server 有专门开关:--long-lived(容器长驻到 Gateway 停止为止)与 --static(预启动模式,server 作为独立容器先跑起来)。

Docker MCP Catalog:300+ 个签名容器化服务器

Catalog 是 Docker 策展的已验证 MCP server 集合,打包为容器镜像经 Docker Hub 分发,规模 300+。构成分四类:经验证的社区 server(带版本与 SBOM 元数据)、合作伙伴工具(New Relic、Stripe、Grafana 等)、Docker 自建并数字签名的本地 server、以及 GitHub / Notion / Linear 这类云托管的远端服务。

可信机制是 Catalog 的核心卖点:每个 server 附带三种 attestation——Docker Build Cloud 构建证明、可验证的来源声明、带密码学签名的 SBOM。mcp/ 命名空间的镜像默认启用签名验证,启用时必须以 digest 引用镜像、pull 和 run 前都会校验。运行时可用 docker mcp gateway run --verify-signatures 显式校验(注:该 flag 的默认值在不同文档源存在差异,以 security.md 的「默认启用」语义为准)。

浏览方式:Docker Desktop 的 MCP Toolkit → Catalog 标签页,或 CLI docker mcp catalog server ls mcp/docker-mcp-catalog。想把自己的 server 送进 Catalog,向 docker/mcp-registry 仓库提 PR——官方原话是审核通过后 24 小时内上线。

一个时效注记:docs.docker.com 当前的 Gateway 页面标注「作为 Docker AI Governance 一部分的 MCP Gateway 为邀请制功能」——开源实现仍在 GitHub 仓库完整可用,但商业产品线的准入政策在变化,部署前查一眼最新文档。

Toolkit 与 docker mcp CLI 速查

docker mcp 命令需要 Docker Desktop 4.62+(Beta features 里启用 MCP Toolkit;无 Desktop 的引擎可手动下载 CLI 插件放到 ~/.docker/cli-plugins/docker-mcp)。子命令地图:

| 子命令 | 用途 | |---|---| | catalog | 管理与浏览 server 目录 | | profile | 把 server + 配置打包成可复用的组合(Desktop 自动启用) | | config | 管理 server 配置项 | | secret | 凭据管理(存本机 OS Keychain) | | gateway | 运行 MCP 网关 | | server / tools | server 管理与工具检查/调用 | | client | 把 Gateway 接到 Claude Code、VS Code 等客户端 | | oauth / feature / version | OAuth 管理、实验特性、版本 |

一条典型的配置流:docker mcp profile create --name web-devdocker mcp profile server add web-dev --server catalog://mcp/docker-mcp-catalog/github-officialdocker mcp profile config <id> --set <server>.<key>=<value>docker mcp gateway run --profile web-dev。server 引用支持四种 scheme:catalog://(OCI 目录)、docker://(任意镜像)、https://(社区 registry)、file://(本地 YAML/JSON)。

凭据不走配置文件:echo <token> | docker mcp secret set github_token,值进本机 Keychain,server 声明式引用。

docker mcp gateway run:stdio / sse / streaming 三种跑法

Gateway 的运行参数不多,但每个都影响架构:

  • --transport stdio|sse|streaming:默认 stdio(挂给单个 client);HTTP 模式(--port 8080 --transport streaming)可服务多个客户端。
  • HTTP 模式默认要求认证:请求必须带 Bearer token(从 MCP_GATEWAY_AUTH_TOKEN 读取或由 Gateway 生成),--allow-unauthenticated 是显式退出项;带 Origin 的浏览器请求只接受 localhost 来源——这是对 DNS rebinding 的直接防御。
  • --secrets docker-desktop:./.env:凭据来源,Desktop Keychain 优先、.env 兜底。
  • 加固三件套:--block-secrets(默认开,扫描工具调用参数与响应中的密钥样式值)、--block-network--cpus/--memory(默认每 server 1 核 2GB)。

一个实战数字:Gateway 冷启动约需 15-25 秒——把客户端的超时设到 60 秒(官方建议),默认 10 秒会在初始化阶段就报超时,这是新手最常见的第一个坑。

对接 Claude Desktop 与 Claude Code

本机客户端的配置几乎不用改——只是把 server 的 command 换成 Gateway:

{
  "mcpServers": {
    "MCP_DOCKER": {
      "command": "docker",
      "args": ["mcp", "gateway", "run", "--profile", "web-dev"]
    }
  }
}

Claude Code 侧验证:claude mcp list 应显示 MCP_DOCKER: docker mcp gateway run - ✓ Connected。也可以用 docker mcp client connect claude-code(支持 13 个客户端)自动写入配置。server 本身的 mcpServers 配置语义不变,客户端配置的其他细节见 MCP 服务器配置指南

自建 Streamable HTTP 服务器的容器化

自己写的 server 想常驻容器,就不需要 Gateway 拉起——直接跑成网络服务,按 2026-07-28 规范的 Streamable HTTP 契约来:

  • 单端点 POST:server 必须提供一个 MCP 端点(如 /mcp),GET/DELETE 返回 405。
  • 必需头:每个 POST 带 MCP-Protocol-VersionMcp-Method/Mcp-NameAccept 同时列 application/jsontext/event-stream
  • 反代配置:起 SSE 流时响应带 X-Accel-Buffering: no(规范点名 nginx),长流周期性发注释行做 keep-alive。
  • 健康检查:Gateway 提供 /health(故意不做认证)专供探针;Compose 官方示例用 wget -O- http://localhost:9011/health、1 秒间隔、60 次重试,client 服务以 depends_on: condition: service_healthy 等它就绪再连 http://gateway:9011/mcp
  • 安全基线:校验 Origin;本机运行只绑 127.0.0.1

Docker Compose 编排:从单 server 到全栈

官方 examples 目录给了完整的渐进路径。最小编排只有三行要素:

services:
  gateway:
    image: docker/mcp-gateway
    command: [--servers=duckduckgo]
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

往上加:secrets 编排(gateway 命令 --secrets=docker-desktop:/run/secrets/mcp_secret + 顶层 compose secrets 指向 .env);--static 模式把 server 作为独立 service 预启动(镜像以 digest 固定、no-new-privileges、cpu/内存限额、docker-mcp-* 标签让 Gateway 认领);再加一个 client service 走 streaming 端点——就是一套 client + gateway + 多 server 的全栈。本机客户端与容器网络内客户端的接入差异(mcpServers 配置 vs URL 直连)两条路线都有官方示例。

2026-07-28 无状态化:容器部署的最大利好

2026-07-28 规范移除了协议级会话与 Mcp-Session-Id(SEP-2567)、移除了 initialize 握手(SEP-2575)——每个请求自包含(版本与能力在 _meta,路由信息镜像到 HTTP 头)。对容器部署的意义值得单独一节(以下为由规范事实推导的工程判断):

  • 滚动更新不再撕断会话:没有会话可黏,K8s 重建 server 容器就是普通的替换 Pod。
  • 负载均衡按请求调度:规范明言中间层可据镜像头路由与检查,不需要会话亲和。
  • 旧客户端有明确兼容行为:对 MCP 端点的 GET/DELETE 回 405、忽略 Mcp-Session-IdLast-Event-ID 头——迁移期可以温和共存。

配套的弃用别忽略:HTTP+SSE 旧 transport(2024-11-05)已正式标记 Deprecated,容器化的迁移目标就是 Streamable HTTP。

安全加固清单

  • 凭据docker mcp secret set 进 Keychain(Desktop 4.43.0 起存储在 Desktop VM 内),server 声明式引用、按 server 隔离;Compose 里走 secrets 注入。
  • 防泄漏--block-secrets 默认开启,工具执行前后都扫描密钥样式值;调用日志只记工具名与参数形状,默认不落原始参数值。
  • 网络--block-network 与 per-server 的 disableNetwork/allowHosts;注意默认并不全局断网——按需收紧,别假设默认安全。远端 URL 默认强制公网 HTTPS、拒绝 loopback/私网/metadata 地址。
  • 容器加固:server 容器自动带 Docker 隔离、no-new-privileges 与 CPU/内存限额;宿主机目录 bind 默认只读,可写 bind 需要精确路径白名单;server 容器默认拿不到你的宿主环境变量。
  • 镜像mcp/ 命名空间默认验签;自建镜像建议同样 digest 固定 + 签名。

生产化:日志、监控、排障

Gateway 内建调用追踪(--log-calls 默认开);/health 端点专供探针;规范层面约定了 OTel trace 上下文透传(traceparent/tracestate/baggage_meta),仓库有 OTel 指标示例。排障三板斧:docker mcp gateway run --verbose --dry-run(看启用了哪些 server、拉哪些镜像、聚合成多少工具)、docker mcp tools ls --verbosedocker mcp tools call search query=Docker——部署后先跑这三条,多数配置问题当场现形。想动手学,Docker 官方有交互式 Lab(7 个模块,从 secrets 注入到自定义 server)。

相关指南

常见问题

stdio MCP 服务器也能容器化吗?

能,但不是把容器当子进程——而是让 MCP Gateway 当 client 的子进程(command: docker, args: [mcp, gateway, run]),由 Gateway 按需把 server 作为容器拉起和管理。client 看到的仍是一个标准 stdio server。

Gateway 的 HTTP 模式需要认证吗?

默认需要:sse / streaming 模式的请求必须带 Bearer token(来自 MCP_GATEWAY_AUTH_TOKEN 或由 Gateway 生成),--allow-unauthenticated 是显式退出项;浏览器来源的请求只接受 localhost Origin。/health 是唯一的未认证端点。

Docker MCP Catalog 里的 server 可信吗?

每个 server 附带构建证明、来源声明与签名 SBOM 三种 attestation;mcp/ 命名空间镜像默认启用签名验证(启用时强制 digest 引用)。机制之外仍建议最小权限:只启用当前任务需要的 server 与工具。

为什么我的 Gateway 一启动客户端就超时?

Gateway 冷启动需要约 15-25 秒,而很多客户端默认超时是 10 秒。把客户端的启动超时提到 60 秒(官方推荐值),或改用 --static 预启动模式。

2026-07-28 规范对容器化部署有什么实际影响?

协议级会话被移除(SEP-2567)、握手被移除(SEP-2575),请求完全自包含——server 容器的重启、替换、横向扩缩不再有「断会话」概念,K8s 滚动更新和按请求负载均衡都变成普通操作。旧客户端会按明确的兼容行为(405、忽略会话头)共存。

不用 Docker Desktop 能用这套工具吗?

能。CLI 插件可手动安装(二进制放到 ~/.docker/cli-plugins/docker-mcp),容器化环境或 WSL2 用 DOCKER_MCP_IN_CONTAINER=1 绕过 Desktop 检查。部分与 Desktop 联动的特性(如 Keychain 凭据存储、profile 自动启用)需要替代方案(--secrets 指向 .env、docker mcp feature enable profiles)。

官方参考资料

本文基于截至 2026 年 9 月 4 日的 Docker 官方文档与 docker/mcp-gateway 仓库(含「Gateway 商业版为邀请制」的时效注记);MCP Gateway 演进很快,以官方文档为准。