你在 AgentBridge 平台 导出 / 下载 的 zip 是一份独立可运行的 MCP server,
内置 Dockerfile,直接 docker build 就能成镜像。
本页展开讲 streamable-http 和 stdio 两种 transport 在 Docker 下的不同打法、compose 编排、客户端接入和常见坑。
通用的 pip + python 自部署方式见 单 Server 部署;
这一页专注容器化这条路径。
从平台点 下载 或用 GET /run/{id}/export 拉下来,通常有这些文件:
| 文件 | 作用 | Docker 部署用得上? |
|---|---|---|
mcp_server.py | MCP Server 主体,所有工具函数和入口 | ✅ 必备 |
requirements.txt | Python 依赖清单 | ✅ 必备(Dockerfile 会读) |
Dockerfile | 容器镜像配方,平台已生成 | ✅ 本页主角 |
tools.json | 工具定义的数据副本(参考) | 📖 参考 |
config.yaml | 配置参考(运行时以环境变量为准) | 📖 参考 |
README.md | zip 自带的简要说明 | 📖 参考 |
导出时选的 transport 决定了容器怎么用:
| transport | 容器特征 | 典型场景 |
|---|---|---|
streamable-http |
监听 0.0.0.0:8080,EXPOSE 8080 |
远端客户端、HTTP 反代、容器化集中部署 |
stdio |
不 EXPOSE 端口,容器走 stdin/stdout 通信 |
Claude Desktop / Cursor / 本地 IDE,容器当 sidecar |
zip 里的 Dockerfile 长这样(平台生成,你不需要手写):
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY mcp_server.py tools.json config.yaml ./
ENV HOST=0.0.0.0
ENV PORT=8080
EXPOSE 8080
CMD ["python", "mcp_server.py"]
# 1. 解压 zip
unzip my-agent.zip -d my-agent
cd my-agent
# 2. 构造镜像(注意末尾的点,表示当前目录作为构建上下文)
docker build -t my-agent:latest .
# 3. 跑起来:把容器 8080 映射到宿主机 8080,
# 用 -e 注入业务 API 地址
docker run -d --name my-agent \
-p 8080:8080 \
-e USER_API_ENDPOINT="https://api.example.com" \
-e API_KEY="sk-xxxxxx" \
my-agent:latest
# 4. 看日志
docker logs -f my-agent
客户端接 http://<docker-host>:8080/mcp(MCP 协议端点),具体路径看 mcp_server.py 里的 mount path。
实际项目里你大概率会同时跑好几个 server,compose 比一堆 docker run 命令好维护:
# compose.yaml
services:
my-agent:
build: .
image: my-agent:latest
container_name: my-agent
restart: unless-stopped
ports:
- "8080:8080"
environment:
USER_API_ENDPOINT: "https://api.example.com"
API_KEY: "${API_KEY}"
HOST: 0.0.0.0
PORT: 8080
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8080/health', timeout=3)"]
interval: 30s
timeout: 5s
retries: 3
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
# 想再起一个?复制一份、改 image 和 port 即可
another-agent:
build: ./another-agent
image: another-agent:latest
container_name: another-agent
ports:
- "8081:8080"
environment:
USER_API_ENDPOINT: "https://api.example.com/v2"
容器里设了 --proxy-headers(如果有),反代转发这几个头即可让 server 拿到真实 IP/协议:
server {
listen 443 ssl;
server_name mcp.example.com;
client_max_body_size 20M;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_http_version 1.1;
proxy_read_timeout 300s;
}
}
stdio 模式的 Dockerfile 没有 EXPOSE —— 容器不监听端口,
通信靠 stdin/stdout。这种方式天然适合被父进程(Claude Desktop、Cursor、其它 MCP host)通过 docker run -i 拉起。
# -i 必须开,否则容器拿不到 stdin
# --rm 跑完即删,免得积一堆停止的容器
docker run -i --rm \
-e USER_API_ENDPOINT="https://api.example.com" \
-e API_KEY="sk-xxxxxx" \
my-agent:latest
编辑 Claude Desktop 的 mcp.json:
~/Library/Application Support/Claude/claude_desktop_config.json%APPDATA%\Claude\claude_desktop_config.json{
"mcpServers": {
"my-agent": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "USER_API_ENDPOINT=https://api.example.com",
"-e", "API_KEY=sk-xxxxxx",
"my-agent:latest"
]
}
}
}
重启 Claude Desktop,工具列表里就会多出 my-agent 注册的所有工具。
Compose 也能跑 stdio 模式,只是要注意不要映射端口:
services:
my-agent:
build: .
image: my-agent:latest
container_name: my-agent
stdin_open: true # 关键:不关 stdin
tty: true # 关键:分配 TTY,容器能正常 IO
environment:
USER_API_ENDPOINT: "https://api.example.com"
API_KEY: "${API_KEY}"
# 注意:不要写 ports:,stdio 模式不监听端口
但 Compose 起 stdio 容器比较别扭 —— Compose 是为"长跑服务"设计的,
stdio 容器更适合被父进程用 docker run -i 拉起。Compose 这种写法仅当你用 K8s/Portainer 当调度器时有用。
平台 不会 把敏感信息写进 zip,所有 secret 通过 -e 或 compose 的 environment 注入:
| 变量 | 含义 | 何时必填 |
|---|---|---|
USER_API_ENDPOINT | 你业务 API 的根 URL | 几乎总得填 |
API_KEY | 鉴权 Key,作为 X-API-Key 转发 | 上游要鉴权时 |
HOST | streamable-http 绑定的 host | 默认 0.0.0.0,改 127.0.0.1 锁本机 |
PORT | streamable-http 监听端口 | 默认 8080 |
具体到你的 server 还可能需要别的 env(看 zip 里的 README.md),逐个 -e 加上即可。
不想让密钥出现在 docker inspect 里,改成 --env-file 读文件:
docker run -d --name my-agent --env-file ./secrets.env -p 8080:8080 my-agent:latest
默认 python:3.11-slim 镜像约 120 MB,装上你的 requirements.txt 后通常 200~300 MB。
如果你想再压一压,改成多阶段构建:
# --- builder:装依赖到独立层 ---
FROM python:3.11-slim AS builder
WORKDIR /build
COPY requirements.txt .
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt
# --- runner:只复制装好的 site-packages ---
FROM python:3.11-slim
WORKDIR /app
COPY --from=builder /install /usr/local
COPY mcp_server.py tools.json config.yaml ./
ENV HOST=0.0.0.0
ENV PORT=8080
EXPOSE 8080
CMD ["python", "mcp_server.py"]
收益取决于 requirements.txt 里的纯 Python 包占比。一般能省 30~50 MB,但维护成本也上来了 —— 小项目没必要。
docker build 报 pip install 失败九成是网络问题。Dockerfile 改用国内源:
RUN pip install --no-cache-dir \
-i https://pypi.tuna.tsinghua.edu.cn/simple \
-r requirements.txt
或者在宿主机配 ~/.pip/pip.conf 的 global.index-url(build 阶段会读到)。
/mcpdocker ps 里容器在 running(不是 restarting)docker logs my-agent 看到 Uvicorn running on http://0.0.0.0:8080curl http://localhost:8080/health 试试Address already in use宿主机 8080 被占。改端口映射:
docker run -p 9000:8080 ... my-agent:latest
# 客户端连 http://<host>:9000/mcp
mcp_server.py 怎么热更新?Docker 没有热加载,改完重 build 即可:
docker build -t my-agent:latest .
docker compose up -d --build # compose 场景
# 或
docker stop my-agent && docker rm my-agent
docker run -d --name my-agent -p 8080:8080 my-agent:latest
改 zip 里的 requirements.txt(或在你 mcp_server.py 引用方维护一份),然后重 build。
不推荐 用 docker exec 进容器 pip install —— 重 build 时会丢,容器层也会变脏。
FastMCP 默认不打印请求体。两种方式:
docker run -e LOG_LEVEL=DEBUG ...(如果 server 实现了)access_log、Caddy 的 log 都能记本项目仓库根目录也有一份 Dockerfile + docker-compose.yml,那是平台自身(即这个 Agent MCP Gateway 网关服务)的容器化部署方案 —— 跟当前页面说的"用 Docker 跑导出的 MCP server"是两件事:
| 本页:Docker 跑 MCP server | 仓库根目录:Docker 跑网关 | |
|---|---|---|
| 看的人 | AgentBridge 平台的使用者 | AgentBridge 平台的开发者 / 运维 |
| 文档格式 | HTML(本页面) | DOCKER_DEPLOYMENT.md |
| 构建上下文 | zip 解压目录(单个 server) | 仓库根目录(整平台) |
| 典型规模 | 1~N 个独立 MCP server | 1 个网关 + 可选 Postgres |
| 持久化 | 通常无状态(可选落 /data) | SQLite/PG 库必须持久化 |