内容
<img src="https://raw.githubusercontent.com/L337-org/docker-mcp/main/assets/icon.png" align="left" width="72" height="72" alt="">
# docker-mcp-server
[](https://glama.ai/mcp/servers/L337-org/docker-mcp)
<!-- mcp-name: io.github.L337-org/docker-mcp-server -->
这是一个功能齐全的MCP服务器,除了让AI代理管理Docker容器、镜像、网络、卷、Swarm服务、秘密、配置、节点、插件等,它还帮助您创建工作流来轻松管理Docker环境。
对于简单的用例,您可以安装后立即使用,无需任何配置 - 加载后,它将自动发现本地Docker套接字,并向您的AI代理公开完整的命令界面。对于更高级的用户,它可以管理多个Docker守护进程,例如本地开发环境和远程生产环境,支持通过TCP、TLS或SSH在一个会话中进行管理。它还可以配置某些守护进程为只读模式,这样您可以在不冒险进行意外更改的情况下监控它们。
MCP服务器还将日志和统计信息等资源公开,以便您进行监控和故障排除,从而使您能够回答诸如“为什么我的容器崩溃了?”,“我的Swarm状态如何?”,“我是否遇到内存压力?”,“我的卷磁盘使用情况如何?”,“我的测试和生产系统之间有什么差异?”等问题。
docker-mcp-server针对新一代支持延迟加载工具的MCP客户端进行了优化。对于仍然急切加载所有工具的客户端,服务器可以可选地配置为从一组域中排除工具(例如,排除'swarm'和'scout'工具),以减少工具列表大小。还可以将MCP服务器设置为“只读”或“无破坏”模式,以防止任何具有写入或破坏能力的工具注册,从而进一步减少占用。
服务器完全在您的机器上运行,可以本地运行,作为[mcpb包](#install-as-a-desktop-extension-mcpb),或[容器化](#run-as-a-container),并且不会发送任何遥测数据。您完全控制服务器 - 请参阅[隐私政策](#privacy-policy)。
## 需求
注意:如果您使用容器化的MCP服务器或MCPB包,Python和uv的需求将自动为您处理。
- 一个可从运行服务器的主机访问的正在运行的Docker守护进程(标准`DOCKER_HOST` / unix套接字约定适用)
- [Python ≥ 3.14](https://www.python.org/downloads/)
- [uv](https://docs.astral.sh/uv/)用于依赖项管理
## 使用服务器
服务器以`docker-mcp-server`发布到[PyPI](https://pypi.org/project/docker-mcp-server/)。在您的AI工具的MCP配置(通常为`mcp.json`或客户端中的等效配置)中添加一个条目,指向它 - `uv`将在首次使用时获取并缓存该包:
```json
{
"mcpServers": {
"docker-mcp-server": {
"command": "uvx",
"args": ["docker-mcp-server"],
"env": {}
}
}
}
```
要固定特定版本,请在包名后追加`==<version>`(例如`docker-mcp-server==1.5.0`)。如果您想将其安装到`PATH`中,`pipx install docker-mcp-server`会为您提供`docker-mcp-server`控制台脚本(还会安装`docker-mcp`别名)。
**从git安装代替.** 要直接从此仓库运行未发布的修订版本:
```json
{
"mcpServers": {
"docker-mcp-server": {
"command": "uvx",
"args": [
"--from",
"git+https://github.com/L337-org/docker-mcp.git",
"docker-mcp-server"
],
"env": {}
}
}
}
```
要固定特定修订版本,请在git URL后追加`@<tag-or-commit>`。
### 安装为桌面扩展(.mcpb)
对于[Claude Desktop](https://claude.com/download),每个[GitHub Release](https://github.com/L337-org/docker-mcp/releases)都附带了一个一键式包,名为`docker-mcp-server-<version>.mcpb`(带有匹配的`.sha256`)。下载它并将其拖放到**设置→扩展**中,或使用**设置→扩展→高级设置→安装扩展...**并选择该文件。安装对话框显示了一个**Docker主机(s)**字段和只读/无破坏/禁用域开关,因此不需要手动编辑JSON。
这是一个[`uv`型包](https://github.com/modelcontextprotocol/mcpb):Claude Desktop的托管`uv`解析依赖项并运行服务器,因此主机前提条件只有Docker本身 - 不需要单独的Python、`uv`或`git`。将**Docker主机(s)**字段留空以使用默认Docker上下文;设置一个端点(`ssh://user@host`)用于远程守护进程,或列出几个(参见[管理多个守护进程](#managing-several-daemons))。
### 以容器形式运行
以容器形式运行服务器完全消除了Python / uv / git的前提条件 - 主机只需要Docker,这是您已经拥有的。预构建的多架构镜像(linux / amd64 + linux / arm64)在每个版本发布到**Docker Hub**(`gavinlucas / docker-mcp-server`)和**GHCR**(`ghcr.io / l337-org / docker-mcp-server`) - 这两个是相同的。指向您的MCP客户端`docker run`:
```json
{
"mcpServers": {
"docker-mcp-server": {
"command": "docker",
"args": [
"run", "--rm", "-i",
"-v", "/var/run/docker.sock:/var/run/docker.sock",
"gavinlucas/docker-mcp-server:latest"
],
"env": {}
}
}
}
```
`-i`是必需的(服务器通过stdio与MCP通信);`--rm`在客户端断开连接时清理容器。要固定版本,请将`:latest`替换为发布标签(例如`:1.5.1`)。要从GHCR拉取,请使用`ghcr.io/l337-org/docker-mcp-server:latest`。
> **镜像重命名.** 从1.5.0开始,镜像发布为`docker-mcp-server`(与PyPI名称匹配)。旧`ghcr.io/gavinlucas/docker-mcp`镜像在1.4.0处冻结,不再更新 - 将新拉取指向`ghcr.io/l337-org/docker-mcp-server`。
**镜像变体.** 两个变体发布到两个注册表(Docker Hub上的`gavinlucas/docker-mcp-server`和GHCR上的`ghcr.io/l337-org/docker-mcp-server`),两者都由一个`Dockerfile`构建。CLI支持的域(Compose,Stack,Buildx,Scout,Context)外壳输出到`docker`CLI及其插件。
| 变体 | 标签 | 大小 | 包含 |
| --- | --- | --- | --- |
| `full` *(默认)* | `:latest`, `:<version>` | ~510 MB | docker CLI + compose + buildx + **scout** |
| `no-scout` | `:no-scout`, `:<version>-no-scout` | ~315 MB | docker CLI + compose + buildx |
Scout的插件二进制文件本身占了`no-scout`到`full`的~195 MB的增加。`no-scout`镜像还默认禁用`DOCKER_MCP_SERVER_DISABLE=scout`,因此scout *工具*不会注册 - 代理永远不会提供其CLI插件不可用的工具(它看到的是一个较小、功能齐全的工具列表,而不是scout工具在每次调用时出错)。在运行时使用`-e DOCKER_MCP_SERVER_DISABLE=...`覆盖,如果您需要更改禁用的集合(注意它替换,而不是追加)。
**自己构建.** 所有变体都从存储库的`Dockerfile`通过构建参数构建:
```bash
docker build -t docker-mcp-server:full . # full (default)
docker build --build-arg INSTALL_SCOUT=0 --build-arg DISABLE_DOMAINS=scout \
-t docker-mcp-server:no-scout . # no-scout
docker build --build-arg INSTALL_CLI=0 -t docker-mcp-server:lite . # lite (仅SDK工具,~165 MB)
```
`lite`镜像(仅docker-py SDK工具 - Compose / Buildx / Scout / Context降级为“插件不可用”)是可构建但不发布的。
**从容器内部访问守护进程.** 镜像默认`DOCKER_HOST`为`unix:///var/run/docker.sock`,因此将主机的套接字挂载到该路径就足够了。但是,主机的套接字位置因平台而异,服务器在启动时会在stderr上打印一个平台感知提示,如果它无法连接:
- **Linux:** `-v /var/run/docker.sock:/var/run/docker.sock`(无root:`-v $XDG_RUNTIME_DIR/docker.sock:/var/run/docker.sock`)。
- **macOS(Docker Desktop):** 实际套接字通常是`~/.docker/run/docker.sock` - 将其挂载到容器路径:`-v $HOME/.docker/run/docker.sock:/var/run/docker.sock`(或启用*设置→高级→允许默认Docker套接字*并使用`/var/run/docker.sock`)。
- **Windows(Docker Desktop / WSL2):** 引擎使用命名管道,而不是Unix套接字 - 优先使用`-e DOCKER_HOST=tcp://host.docker.internal:2375`(在Docker Desktop中启用TCP端点)。该端点是**未认证和未加密的** - 将其绑定到localhost,禁用时请勿使用,并使用TLS或`DOCKER_HOST=ssh://...`用于任何远程守护进程。
- **远程/ TLS / SSH守护进程:** 跳过套接字挂载并传递`-e DOCKER_HOST=...`(以及下面的TLS变量)- 参见[与远程守护进程通信](#talking-to-a-remote-daemon)。
**主机文件系统访问.** 在容器内,文件路径工具(`image_save` / `container_export`带有`dest_path`,`image_load` / `container_archive_put`带有`from_file`,`container_archive_get_to_file`和`project_dir` / `files`)解析容器**内部**的路径,而不是您的主机。绑定挂载任何您想通过交换文件的文件夹 - 使用**相同的路径内部和外部**保持主机和容器路径相同:
```
-v $HOME/docker-work:$HOME/docker-work
```
如果您调用其中一个工具的路径不在绑定挂载上,服务器会直接拒绝并显示一条消息,告诉您确切需要添加哪个`-v`。
### 与远程守护进程通信
当设置`DOCKER_HOST`时,服务器直接使用它(通过`docker.from_env()`,因此`DOCKER_TLS_VERIFY` / `DOCKER_CERT_PATH`也被尊重)。常见的覆盖环境变量:
```json
"env": {
"DOCKER_HOST": "tcp://remote-host:2375",
"DOCKER_TLS_VERIFY": "1",
"DOCKER_CERT_PATH": "/path/to/certs"
}
```
**默认守护进程(无`DOCKER_HOST`)。** 当`DOCKER_HOST`未设置时,服务器通过`docker.from_env()`解析守护进程的方式与`docker`CLI相同,而不是假设`/var/run/docker.sock`:它遵循活动的Docker **上下文**(`DOCKER_CONTEXT`,否则`currentContext`来自`~/.docker/config.json`,从该上下文的`meta.json`读取端点),如果该端点产生任何结果,它会探测已知套接字位置(`~/.docker/run/docker.sock`适用于Docker Desktop 4.13+, `$XDG_RUNTIME_DIR/docker.sock`适用于无root,然后`/var/run/docker.sock`)。这是因为`docker.from_env()`单独忽略上下文,并会回退到`/var/run/docker.sock` - **Docker Desktop 4.13+默认情况下不再创建此项**(它使用`desktop-linux`上下文,除非您启用*设置→高级→允许默认Docker套接字*,否则无法在此处访问)。优先级:非空`DOCKER_HOST`始终获胜并直接通过`docker.from_env()`(忽略上下文);`DOCKER_CONTEXT` / `currentContext`仅在`DOCKER_HOST`未设置时进行咨询,套接字探测仅在两者都不解析时进行。远程上下文中附加的TLS材料不会自动应用 - `tcp://` + TLS上下文仍然需要`DOCKER_HOST` / `DOCKER_CERT_PATH`。
**通过SSH.** `DOCKER_HOST=ssh://user@remote-host`通过纯Python传输(paramiko,由`docker[ssh]`依赖项拉取)得到支持 - 没有**系统`ssh`二进制文件需求**,因此它在主机安装和容器镜像内部都可以正常工作。它使用您的正常SSH设置:
- **密钥/代理.** 使用基于密钥的身份验证;将密钥加载到您的代理(`ssh-add`)并确保`SSH_AUTH_SOCK`已设置在服务器的环境中(或将密钥放在默认`~/.ssh/id_*`路径)。
- **已知主机.** paramiko会将主机密钥与`~/.ssh/known_hosts`进行验证并**拒绝未知主机**。通过受信任的渠道验证主机密钥后添加主机密钥 - 使用`ssh user@remote-host`交互式连接并确认提示,或在追加之前将`ssh-keyscan remote-host | ssh-keygen -lf -`与已知良好的指纹进行比较。避免盲目将`ssh-keyscan`直接写入`known_hosts`,这会信任返回的密钥(包括中间人(MITM)的密钥)。
- **在容器内.** 挂载您的SSH材料只读`-v $HOME/.ssh:/root/.ssh:ro`(密钥+ `known_hosts`)- 或转发您的代理套接字;不需要套接字挂载,也不需要`ssh`包。
CLI支持的工具(Compose,Buildx,Context,Scout)外壳输出到`docker`CLI,它原本会使用*系统* `ssh`二进制文件通过`ssh://`端点。相反,`run_docker()`检测`DOCKER_HOST=ssh://...`并透明地启动一个每个调用的本地TCP代理(`docker_mcp/tools/_ssh_proxy.py`),它打开与docker-py相同的paramiko连接,运行`docker system dial-stdio`并指向CLI子进程`tcp://127.0.0.1:<ephemeral port>`,仅用于该调用。
因此,CLI支持的工具使用与上述docker-py工具相同的凭证和主机密钥策略 - **没有系统`ssh`二进制文件用于直接连接**,在容器镜像内部和主机安装上完全相同。例外情况是`ProxyCommand`在`~/.ssh/config`(堡垒/跳转主机设置):paramiko按原样运行该命令,并且通常是`ssh -W %h:%p ...`,因此跳转主机跳跃仍然会外壳输出到系统`ssh`客户端,即使直接连接不使用。
该临时`127.0.0.1`侦听器通过localhost-only桥接到远程(root-equivalent)守护进程,持续时间仅限于单个CLI调用,因此任何共享相同环回端口的进程都可以在此简短窗口期内访问它,并且在容器内,它甚至更窄,仅限于该容器内的进程的网络命名空间。守护进程仍然是信任边界(参见[安全考虑](#security-considerations))。
### 管理多个守护进程
上述所有内容都针对一个守护进程。要在**单个会话中管理多个** - 例如本地开发环境和远程生产守护进程 - 设置 **`DOCKER_MCP_SERVER_HOSTS`**为逗号分隔的`name=endpoint`对列表:
```json
"env": {
"DOCKER_MCP_SERVER_HOSTS": "local=auto, prod=ssh://ops@prod.example.com(ro)"
}
```
- **`endpoint`**是`auto`(您的默认上下文/套接字,如上所述),`local`(平台本地套接字,忽略上下文),或`unix://` / `tcp://` / `ssh://` / `npipe://` URL。`ssh://`是推荐的远程传输协议(每个主机通过您的SSH密钥,无TLS证书管道)。`tcp://`守护进程上的TLS使用`(tls=<dir>)`标记指向证书目录,例如`prod=tcp://prod:2376(tls=/etc/docker/prod)`。该目录必须包含 **`ca.pem`**(守护进程始终根据它验证 - 因此自签名守护进程有效,您只需在此处固定其证书);添加 **`cert.pem`**和 **`key.pem`**仅当守护进程需要客户端证书(相互TLS)。没有未经验证的TLS模式 - TLS连接始终验证守护进程,因此加密永远不会没有验证。
- **`(ro)`**在端点后标记主机 **只读**:变异和破坏性工具拒绝对此进行操作。此是每个主机保护的调用时间独立于服务器范围的`DOCKER_MCP_SERVER_READONLY`开关 - 将生产`(ro)`标记为只读,代理可以无限期检查,但无法更改,而本地保持读写。
- **单个守护进程,简写形式。** 带有`name=`的裸值是简写形式 - `DOCKER_MCP_SERVER_HOSTS=ssh://ops@prod`(或`auto`,或空白)。因此,此单个字段也涵盖了单个远程情况。`DOCKER_HOST`在`DOCKER_MCP_SERVER_HOSTS`设置时继续工作,但 **`DOCKER_MCP_SERVER_HOSTS`接管时**(然后忽略`DOCKER_HOST`,并发出一条一次性通知到stderr)。
### 代理可以执行的操作
加载后,代理会获取按 Docker 域分组的 MCP 工具。以下是一些示例:
- **容器** — `container_run`、`container_list`(`managed_only=True`仅列出此服务器创建的容器 - 请参阅[源标签](#源标签))、`container_exec`、`container_logs`、`container_stop`、`container_commit`、`container_wait`(阻塞直到退出,`until="healthy"`以轮询运行状况检查,或`until="log-match"`以轮询包含`pattern`的日志行)、`container_export` / `container_archive_get_to_file` / `container_archive_put`(流式传输tar存档到/从主机路径)
- **镜像** — `image_build`、`image_pull`、`image_push`、`image_tag`、`image_prune`、`image_save` / `image_load`(流式传输镜像tarball到/从主机路径通过`dest_path` / `from_file`)
- **网络 / 卷** — `network_create`、`network_connect`、`volume_create`、`volume_prune`
- **Swarm** — `swarm_init`、`swarm_join_tokens`(关闭初始化 → 加入循环)、`swarm_update`(旋转加入令牌 / 解锁密钥)、`service_create`、`service_scale`、`service_rollback`(重新应用上一个服务规范)、`service_wait`(阻塞直到任务收敛,或滚动更新完成)、`node_list`、`node_wait`(阻塞直到节点达到目标状态 - 例如`ready`加入后)、`node_remove`、`secret_create`、`config_create`
- **系统** — `system_ping`、`system_info`、`system_version`、`system_df`、`system_events`、`host_list`(配置的守护进程和默认守护进程 - 请参阅[管理多个守护进程](#管理多个守护进程))、`system_login` / `system_logout`(缓存或清除注册表凭证)、`system_reconnect`(重建主机的SDK客户端以恢复卡住的连接)
- **Compose** — `compose_up`、`compose_down`、`compose_stop`、`compose_start`、`compose_restart`、`compose_pause` / `compose_unpause`、`compose_kill`、`compose_ps`、`compose_list`、`compose_images`、`compose_top`、`compose_port`、`compose_logs`、`compose_config`、`compose_build`、`compose_pull`、`compose_run`、`compose_exec`、`compose_cp`、`compose_wait` *(包装`docker compose`CLI插件)*
- **堆栈** — `stack_deploy`、`stack_list`、`stack_ps`、`stack_services`、`stack_remove` *(将Compose文件部署到Swarm作为堆栈;包装`docker stack`CLI - 需要Swarm管理器)*
- **上下文** — `context_list`、`context_inspect`、`context_create`、`context_use`、`context_remove` *(包装`docker context`CLI)*
- **注册表 / Hub** — `registry_tags`、`registry_tag_wait`(阻塞直到特定标签落地 - 例如等待CI推送)、`registry_manifest`、`registry_image_config`(在不拉取的情况下读取镜像的环境/入口点/标签)、`hub_tags`、`hub_repo_info`、`hub_rate_limit`(剩余拉取预算) *(HTTPS到OCI v2注册表和Docker Hub API - 不需要守护进程;对短暂429进行透明重试)*
- **Buildx** — `buildx_build`、`buildx_bake`、`buildx_imagetools_inspect`、`buildx_imagetools_create`、`buildx_list`、`buildx_inspect`、`buildx_du`、`buildx_history_list` / `buildx_history_inspect`(深入过去的构建记录)、`buildx_prune`、`buildx_create`、`buildx_use`、`buildx_remove` *(包装`docker buildx`CLI插件)。使用`buildx_imagetools_*`代替`docker manifest` - 该命令处于维护模式,缺乏对OCI镜像索引和证明的支持。*
- **Scout** — `scout_cves`、`scout_quickview`、`scout_recommendations`、`scout_compare`、`scout_sbom` *(包装`docker scout`CLI插件;大多数功能受益于主机上运行的`docker login`)*
SDK支持的表面镜像反映了 [Docker SDK参考](https://docker-py.readthedocs.io/en/stable/) — 如果在那里记录了它,那么在这里就可用。Compose和Context表面遵循 [Compose CLI](https://docs.docker.com/reference/cli/docker/compose/) 和 [docker context](https://docs.docker.com/reference/cli/docker/context/) 参考。
服务器还发布了Python的Docker SDK参考和选定的Docker CLI / 注册表参考作为MCP资源,以便代理可以在运行时查阅它们:读取 `docker-docs://contents` 获取章节索引,然后 `docker-docs://<section>` (例如 `docker-docs://containers`、`docker-docs://compose`、`docker-docs://oci-distribution-spec`、`docker-docs://dockerfile`、`docker-docs://build-best-practices`、`docker-docs://engine-security`、`docker-docs://engine-api`)获取渲染页面。对于无法读取资源的MCP客户端(例如Claude Desktop,Cursor),`docs_lookup`工具镜像了相同的内容 - 调用它时不带参数获取章节索引,或 `docs_lookup(section=...)` 获取页面;它始终可用,无论`DOCKER_MCP_SERVER_DISABLE`如何。另一个资源`docker-mcp://tool-catalog`列出了此服务器了解的每个工具及其域、变异类别以及活动配置是否注册了它 - 可用于确认工具的影响范围或为什么某个工具从实时列表中缺失。
容器、服务和节点的可观察性也作为资源公开,以便客户端可以在不调用工具的情况下附加实时状态作为上下文:读取 **`docker://containers`** 获取每个容器(正在运行和停止)的索引及其状态和每个容器的资源URI,然后 **`docker-logs://<id-or-name>`** 获取容器日志的限定尾部(即使在退出后仍可读取 - 方便诊断原因)和 **`docker-stats://<id-or-name>`** 获取正在运行的容器的计算资源使用情况总结(CPU%,内存,网络和块I / O)。 **`docker://services`** 是相同的模式,用于Swarm服务 - **`service-logs://<id-or-name>`** 获取限定日志尾部和 **`service-tasks://<id-or-name>`** 获取计算任务/滚动总结(正在运行与期望的任务计数,失败任务和当前滚动更新状态)。 **`docker://nodes`** 仅限索引(状态,可用性,角色和节点管理器可达性) - 可用于在不重新查询`node_list`的情况下注意到节点在就绪/关闭之间波动。这些补充了等效的工具(`container_logs`/`container_stats`,`service_logs`,`node_list`)并且在禁用其域(`containers`/`services`/`nodes`)时隐藏。
### 示例提示
许多AI客户端允许您直接调用已注册的MCP提示(在Claude Code中,键入`/`以查看它们)。服务器在`docker_mcp/tools/prompts.py`中提供了一小部分模板库,这些模板构建了多步骤工作流 - 它们发出一个结构化的计划,然后代理使用docker工具执行该计划。
**在SDK文档中查找内容**
```
/lookup_docker_docs section=services
/verify_docker_method method=containers.run section=containers
```
…或者直接用英语询问:
> 读取 `docker-docs://networks` 并告诉我 `create` 和 `connect` 之间的区别。
> 在更改任何代码之前,请检查 `docker-docs://containers` 并确认 `run` 接受 `restart_policy` 参数。
**创建和管理容器**
```
/deploy_container image=nginx:1.27 name=web
/monitor_container_fleet
/triage_incident window_minutes=30
/troubleshoot_container container=api-1
/migrate_container container=api-1 new_image=myorg/api:v2
/inspect_stack label=com.example.app=web
/clean_environment scope=stopped
/plan_compose_stack description="wordpress + mysql sharing a named volume"
```
**Compose、上下文和注册表**
```
/deploy_compose_project project_dir=/srv/myapp
/troubleshoot_compose_project project_dir=/srv/myapp
/deploy_swarm_stack stack_name=web compose_file=/srv/myapp/docker-stack.yml
/audit_docker_contexts
/find_latest_image_tag image=ghcr.io/org/repo
```
**审计、安全性和主机操作**
```
/review_dockerfile dockerfile_path=/srv/myapp/Dockerfile
/audit_container_security
/debug_container_networking source=web target=db
/investigate_disk_usage
/backup_volume volume=pgdata dest_path=/backups/pgdata.tar
/restore_volume volume=pgdata source_path=/backups/pgdata.tar
/audit_swarm_health
```
**Buildx、Scout和多架构清单**
```
/plan_multiarch_build image=ghcr.io/org/app:v1 platforms=linux/amd64,linux/arm64
/audit_image_cves image=alpine:3.19
/compare_image_versions old_image=org/app:v1 new_image=org/app:v2
/recommend_base_image image=org/app:v1
/inspect_multiarch_manifest image=alpine:3.19
/create_multiarch_manifest target_tag=org/app:v1 source_tags=org/app:v1-amd64,org/app:v1-arm64
/migrate_from_docker_manifest
```
…或者用英语:
> 拉取 `redis:7-alpine` 并将其作为名为 `cache` 的容器运行在新的 `app-net` 网络上,仅在该网络内公开端口 6379。
> 容器 `api-1` 不断重启 - 获取最后 200 行日志,检查其状态和退出代码,并告诉我出了什么问题,然后再进行任何更改。
> 用 `nginx:1.27` 替换正在运行的 `web` 容器,同时保留其当前端口、挂载和重启策略。
> 计划一个带有私有网络和命名卷的 wordpress + mysql 堆栈。 在创建任何内容之前向我展示计划。
> 显示标记为 `com.example.app=web` 的所有容器、网络和卷的表格。 不要更改任何内容。
> 我们磁盘空间紧张 - 显示 `system_df`,修剪停止的容器和悬挂的镜像,然后再次显示 `system_df`。 跳过卷。
> 启动 `/srv/myapp` 中的 compose 项目,但向我展示渲染后的配置并拉取镜像后再启动任何内容。
> 列出我的 Docker 上下文并告诉我此 MCP 服务器当前正在与哪个守护进程通信。
> 在不拉取的情况下查找 `ghcr.io/org/repo` 的最新稳定标签,并告诉我它支持哪些平台。
## 配置
> **环境变量命名。** 服务器的环境变量命名为 `DOCKER_MCP_SERVER_*` 以匹配发布的包名。 2.0之前的 `DOCKER_MCP_*` 别名拼写不再受支持 - 有关完整的1.x → 2.0更改列表,请参阅 `MIGRATION-2.0.md`。
要选择服务器要连接到的 **哪个守护进程**,请参阅 [连接到远程守护进程](#连接到远程守护进程) 和 [管理多个守护进程](#管理多个守护进程)(`DOCKER_MCP_SERVER_HOSTS` / `DOCKER_HOST`)。下面的变量限制了注册哪些工具。
三个环境变量限制了服务器启动时注册的工具。因为它们在注册时删除工具,所以禁用的工具永远不会出现在客户端的工具列表中 - 这是服务器端的保证,而不是客户端提示。 将两个布尔开关设置为 `1` / `true` / `yes` / `on`:
- **`DOCKER_MCP_SERVER_READONLY`** - 仅注册只读工具(查询,日志/数据读取,扫描)。省略了更改状态的每个工具。 将此用于仅限监控或检查的代理,这些代理不应该能够修改任何内容。
- **`DOCKER_MCP_SERVER_NO_DESTRUCTIVE`** - 注册除破坏性工具之外的所有工具(`remove_*`、`prune_*`、`container_kill`、`compose_down`、`swarm_leave`、`context_remove`、`buildx_prune`、`buildx_remove`)。一种“无数据丢失”模式,允许创建和启动资源。`DOCKER_MCP_SERVER_READONLY` 更严格,如果两者都设置,则优先。
- **`DOCKER_MCP_SERVER_DISABLE`** - 以逗号分隔的列表,以整个方式删除域(功能区域),无论类别如何:例如 `DOCKER_MCP_SERVER_DISABLE=swarm,services,nodes,configs,secrets` 从单个主机服务器中删除整个Swarm表面,而 `DOCKER_MCP_SERVER_DISABLE=scout,buildx` 修剪了构建/扫描工具,代理永远不会使用。 域是工具模块的名称 - `containers`、`images`、`networks`、`volumes`、`compose`、`stack`、`context`、`buildx`、`scout`、`registry`、`swarm`、`services`、`nodes`、`plugins`、`configs`、`secrets`、`system`。 名称不区分大小写;无法识别的名称被忽略(并在下面的`unknown_disabled_domains`工具目录中显示)。 这与类别开关相结合 - 仅当工具的类别存活 **且** 其域被启用时,工具才会注册。 禁用域不仅会删除其工具:匹配的工作流 **提示** 将被跳过(以便代理不会被传递一个驱动程序,而该服务器不再公开的特性区域 - 例如禁用 `scout` 会删除 `audit_image_cves` 提示,该提示将指示代理调用一个未注册的工具),并且匹配的文档 **资源** 将从 `docker-docs://contents` 中隐藏(例如 `scout` / `scout-cli` 部分)。 工具目录的 `prompts` 列表和 `disabled_doc_sections` 字段使两者都可审计。 修剪代理不需要的域还可以减少客户端必须推理的工具列表大小,这在服务器大约有 150 个工具时很重要。
独立地,每个注册的工具都带有MCP `ToolAnnotations` - 查询上的 `readOnlyHint` 和破坏性操作上的 `destructiveHint`(以及 `idempotentHint` 在prune家族上)- 因此像Claude Code这样的客户端可以自动允许安全的读取并阻止破坏性调用。 分类位于 `TOOL_CATEGORIES` 中 `docker_mcp/server.py`。 要查看完整的画面 - 每个工具及其域、类别以及活动开关是否注册了它 - 请阅读 **`docker-mcp://tool-catalog`** MCP资源。
对于私有注册表,HTTPS支持的 `registry_*` 工具在没有明确的 `username`/`password` 参数的情况下会回退到服务器环境中的 **`DOCKER_MCP_SERVER_REGISTRY_USERNAME`** / **`DOCKER_MCP_SERVER_REGISTRY_PASSWORD`**。 显式参数优先;环境对不会被许多MCP客户端逐字记录的工具参数很有用 - 密码可能是一个个人访问令牌。
### 源标签
此服务器通过此服务器创建的 **每个Docker对象** - 容器、网络、卷、Swarm服务、配置和秘密 - 都贴上了 `docker-mcp-server.*` 标签,记录了此服务器创建了它(`docker-mcp-server.managed=true`)、服务器版本、原始工具和创建时间戳。 这允许您(或清理作业)稍后使用单个 `docker ... --filter label=docker-mcp-server.managed=true` 枚举确切的代理创建的占用; `managed_only=True` 参数在 `container_list`、`network_list`、`volume_list` 和 `service_list` 是工具快捷方式(它与您传递的任何其他 `filters` 结合使用)。 标记是附加的(如果您自己传递的标签在键冲突时始终获胜),并且唯一命名空间,因此默认情况下它是安全的; **`DOCKER_MCP_SERVER_NO_LABELS=1`** 完全关闭它。 镜像构建 **不** 被标记,因为构建标签会更改生成的镜像摘要。
要仅删除服务器创建的内容 - 而不是其他内容 - 使用 **`prune_managed`** 工作流提示,它将每个删除步骤限定为 `docker-mcp-server.managed=true` 标签(仅当您传递 `include_volumes=True` 时才包括卷,并且仅在确认后)。
### 示例:只读监控服务器
所有这些都放在您的MCP客户端配置中的服务器条目的 `env` 块中(与上面的 `DOCKER_HOST` 相同)。 例如,针对远程守护进程的只读检查服务器:
```json
{
"mcpServers": {
"docker-mcp-server-readonly": {
"command": "uvx",
"args": [
"--from",
"git+https://github.com/L337-org/docker-mcp.git",
"docker-mcp-server"
],
"env": {
"DOCKER_HOST": "tcp://staging-host:2376",
"DOCKER_TLS_VERIFY": "1",
"DOCKER_MCP_SERVER_READONLY": "1"
}
}
}
}
```
将 `DOCKER_MCP_SERVER_READONLY` 替换为 `DOCKER_MCP_SERVER_NO_DESTRUCTIVE` 以允许创建/启动/部署同时阻止 `remove_*` / `prune_*` / `container_kill` 不可能。 您也可以在不同名称下注册同一个服务器两次 - 一个全访问入口,您需要时启用它和一个只读条目用于日常使用。 使用 `claude mcp`(Claude Code),等效的是:
```bash
claude mcp add docker-mcp-server-readonly \
--env DOCKER_MCP_SERVER_READONLY=1 \
-- uvx --from git+https://github.com/L337-org/docker-mcp.git docker-mcp-server```
## 安全考虑
将此服务器连接到AI代理授予它与配置的守护进程本地Docker CLI会话相同的访问级别。 这是非常广泛的:守护进程的套接字实际上等同于在运行它的主机上的根目录。 将代理视为特权用户,在启用服务器之前权衡以下风险。
- **使用范围守护进程。** 优先考虑将`DOCKER_HOST`指向仅限代理可以触及的工作负载的专用守护进程(开发虚拟机,远程沙盒,Docker Desktop,无根安装),而不是生产套接字。 守护进程是信任边界 - 没有每个工具的授权层。
- **作为容器运行。** 将`/var/run/docker.sock`挂载到容器中授予它与uvx安装程序相同的根等效访问权限 - 既不多也不少,但在`docker run`行中显式表达。 相同的范围守护进程建议适用:优先考虑为代理可以控制的守护进程挂载套接字或指向`DOCKER_HOST`。 注意,当容器化时,文件路径工具读取和写入**容器的**文件系统,因此它们只能访问您绑定挂载的宿主目录(参见[作为容器运行](#run-as-a-container))。 作为事故防护,破坏性容器生命周期工具(`container_remove`,`container_kill`,`container_stop`,`container_restart`,`container_pause`)拒绝对服务器**自己的**容器执行操作,因此代理无法在调用过程中结束自己的会话;这是方便,而不是安全边界(可以通过`DOCKER_MCP_SERVER_ALLOW_SELF_TERMINATE=1`绕过,并且人类始终可以从宿主 shell 恢复容器),并且它不限制守护进程特权代理影响宿主的许多其他方式。
- **特权容器和主机挂载。** `container_run`接受`privileged=True`和任意`volumes`。 特权容器或绑定挂载宿主的`/ `可以轻松逃逸到宿主文件系统。 除非您已审查请求,否则请避免让代理设置这些。 编写文件也可以声明相同 - 在批准`compose_up`之前,请查看渲染的`compose_config`输出。
- **直通`extra_kwargs` / `updates`绕过可见模式。** `container_run`,`container_create`,`service_create`(`extra_kwargs`)和`container_update`,`service_update`(`updates`)将任意字典直接转发到Docker SDK。 如果客户端在工具的声明参数上设置了`privileged=False`,则可以通过`extra_kwargs={"privileged": True, "pid_mode": "host"}`绕过客户端的闸门。 这些逃生口与“守护进程是信任边界”的模型一致,但您在MCP客户端层构建的任何允许/拒绝策略都必须考虑它们,而不仅仅信任命名参数。
- **注册表凭证。** 许多MCP客户端逐字记录工具调用,因此请将通过工具传递的任何密码或`auth_config`视为公开。
- **SDK支持的工具**(`system_login`,`image_push`,`image_registry_data`)直接接受凭证 **并且** 可以重用`docker login`在`~/.docker/config.json`中缓存的凭证。 优先考虑在运行此MCP服务器的主机上运行`docker login`一次,并保持凭证参数未设置。 (注意:这是运行服务器的主机,而不是守护进程 - 当`DOCKER_HOST`指向远程守护进程时相关。)传递给`system_login`的凭证在服务器内存中缓存,直到客户端生命周期结束; `system_logout`清除该内存缓存(所有注册表或一个)而不触及`~/.docker/config.json`,而`system_close` / `system_reconnect`通过丢弃客户端清除它。 没有守护进程端的会话需要结束 - 引擎的`/auth`端点仅验证。
- **HTTPS支持的注册表工具**(`registry_tags`,`registry_tag_wait`,`registry_manifest`,`registry_image_config`,`hub_tags`,`hub_repo_info`,`hub_rate_limit`)直接通过HTTPS与注册表通信,**不**读取`~/.docker/config.json`。 `registry_*`工具接受`username` / `password`用于私有注册表 - 或者,更好的是,从服务器环境中读取`DOCKER_MCP_SERVER_REGISTRY_USERNAME` / `DOCKER_MCP_SERVER_REGISTRY_PASSWORD`,以便凭证永远不会传输工具参数(参见[配置](#configuration)); `hub_*`工具目前仅支持公共Hub存储库。 如果通过参数传递凭证,请使用具有最低所需范围的每个调用令牌,而不是长期有效的密码。 当注册表以`Bearer`身份验证挑战作出响应时,服务器在发送任何内容之前验证令牌`realm`所指向的内容:该方案必须为http / https,纯http到非本地主机将被拒绝,并且不允许公共注册表将凭证令牌请求重定向到私有/环回地址(SSRF防护)。 真正的本地开发注册表(例如`localhost:5000`)仍可以使用本地领域。
- **Swarm密钥材料也会通过工具调用传输。** 除了注册表凭证外,多个Swarm工具通过参数或返回值传输密钥材料,MCP客户端可能会记录这些:`secret_create(data=...)`和`config_create(data=...)`将有效载荷作为参数,`secret_inspect` / `config_inspect`返回存储的对象,`swarm_join(join_token=...)`和`swarm_unlock(key=...)`接受群集加入/解锁密钥,而`swarm_unlock_key`和`swarm_join_tokens` **返回**群集凭证(通过`swarm_update`轮换旧令牌)- 管理员加入令牌允许其持有者加入Swarm作为管理员(群集中的根等效)。 将所有这些视为在记录工具流量的任何客户端中公开,并优先通过主机而不是通过代理配置Swarm密钥和读取加入令牌。 如果代理永远不需要允许节点,请使用`DOCKER_MCP_SERVER_DISABLE=swarm`删除整个曲面(参见[配置](#configuration))。
- **`container_exec`,`compose_exec`和`compose_run`运行任意命令。** 当命令的任何部分源自代理控制的输入时,请使用不调用shell的exec-form argv列表(例如`["python", "-V"]`)。 像`["sh", "-c", template]`这样的列表会调用shell,并将在不受信任的子字符串中解释shell元字符。
- **容器存档路径。** `container_archive_get`和`container_archive_put`将提供的路径原样转发到守护进程。 容器是信任边界 - 如果您不信任其文件系统,请不要假设`..`遍历将被拒绝。
- **文件路径有效载荷工具读取和写入服务器主机的文件系统。** `image_save`,`container_export`(使用`dest_path`)和`container_archive_get_to_file`写入运行此MCP服务器的主机上的`dest_path`(除非`overwrite=True`,否则拒绝覆盖现有文件); `image_load`和`container_archive_put`(使用`from_file`)读取主机路径; `compose_cp`在服务容器和主机路径之间复制。 这些以服务器用户身份运行,因此代理可以写入该用户可以写入的任何文件,并读取它可以读取的任何文件。 当您不信任代理访问主机文件系统时,请优先使用带上限的字节工具(上限为32 MiB)。 `DOCKER_MCP_SERVER_READONLY`还会删除主机写入工具 - 但请注意它不是针对它们:它仅注册只读工具,因此`image_load`和`container_archive_put`(以及其他所有变异/破坏性工具)也会被删除。 没有仅删除文件写入器的开关。
- **破坏性操作没有内置确认。** `prune_*`,`remove_*`,`container_kill`,`swarm_leave`,`compose_down(volumes=True)`,`compose_kill`,`stack_remove`(拆除堆栈中的每个服务),`buildx_prune`(始终使用`--force`运行)和`buildx_remove`立即执行。 这些工具带有`destructiveHint`注释,因此像Claude Code这样的客户端可以控制它们,而附带的`clean_environment`提示要求代理在清除卷之前确认 - 但工具调用本身不受服务器的限制。 对于硬保证,请使用`DOCKER_MCP_SERVER_NO_DESTRUCTIVE=1`(完全删除它们)或`DOCKER_MCP_SERVER_READONLY=1`(参见[配置](#configuration)); 对于审批步骤,请在MCP客户端配置它。
- **CLI shell-out攻击面。** Compose,Context,Buildx和Scout工具在运行此MCP服务器的主机上启动`docker`子进程。 每个调用都将参数作为列表(无shell,无元字符解释),通过`shutil.which`解析二进制文件,并针对清理的环境运行(仅DOCKER_HOST和相关变量)。 位置值(图像引用,服务/上下文/构建器名称,构建上下文)如果以`-`开头,则会额外被拒绝,因此不能通过参数走私(例如,名为`--output=…`的服务); `compose_exec` / `compose_run`中的尾随命令除外,该命令旨在成为任意argv。 提供给`compose_*`的文件系统路径(project_dir,files)由服务器主机上的docker CLI读取 - 传递不熟悉的路径可能会公开服务器用户可以读取的任何组合文件。
- **守护进程集在启动时固定;请有意选择它。** 当`DOCKER_HOST` / `DOCKER_MCP_SERVER_HOSTS`未设置时,服务器的**初始** SDK连接遵循您的活动Docker上下文(`DOCKER_CONTEXT` / `currentContext`)- 与您的`docker` CLI目标相同的守护进程 - 因此如果该上下文指向远程或生产守护进程,代理也会连接到那里。 在启动服务器之前,请设置`DOCKER_MCP_SERVER_HOSTS`(或`DOCKER_HOST`,或选择范围上下文)以有意锁定目标(s);使用`DOCKER_MCP_SERVER_HOSTS`时,`auto` / `local`端点被解析并**固定在启动时**,因此如果上下文稍后更改,它们不会漂移。 启动后,`context_use`仅更改后续CLI支持的工具的CLI默认值; SDK支持的工具继续使用其连接的守护进程池客户端。 **没有运行时方法引入或重定向到任意端点的守护进程** - `system_reconnect`仅重建已配置主机的客户端(以恢复卡住的连接),它不能指向其他地方;要添加或更改守护进程,请编辑`DOCKER_MCP_SERVER_HOSTS`并重启。 这故意关闭了一个信任扩展向量(代理无法在会话过程中将根等效边界移动到未经检查的端点)。 `context_create(skip_tls_verify=True)`为上下文禁用TLS验证;仅对受信任的本地守护进程使用。
- **每主机只读是一个事故防护,而不是安全边界。** `DOCKER_MCP_SERVER_HOSTS`中标记为`(ro)`的主机使变异/破坏性工具在调用时拒绝对它执行操作(并且对于多个主机,写入需要显式命名目标主机 - 因此代理不会因省略而更改错误的守护进程)。 像`guard_not_self`一样,这是进程内的方便:它通过此服务器的工具约束代理,但守护进程本身是信任边界,因此对于代理永远不需要修改的主机,请优先指向真正只读或范围守护进程,而不是仅依赖标记。
## 软件包和列表
| 频道 | 链接 |
| --- | --- |
| PyPI | [docker-mcp-server](https://pypi.org/project/docker-mcp-server/) |
| GHCR(容器) | [ghcr.io/l337-org/docker-mcp-server](https://github.com/L337-org/docker-mcp/pkgs/container/docker-mcp-server) |
| Docker Hub(容器) | [gavinlucas/docker-mcp-server](https://hub.docker.com/r/gavinlucas/docker-mcp-server) |
| 桌面扩展(.mcpb) | [GitHub Releases](https://github.com/L337-org/docker-mcp/releases) |
| 官方MCP注册表 | [io.github.L337-org/docker-mcp-server](https://registry.modelcontextprotocol.io/v0.1/servers/io.github.L337-org%2Fdocker-mcp-server/versions) |
| Glama | [docker-mcp-server](https://glama.ai/mcp/servers/L337-org/docker-mcp) |
| mcp.so | [docker-mcp-server](https://mcp.so/server/docker-mcp-server/GavinLucas) |
| awesome-mcp-servers | [punkpeye/awesome-mcp-servers](https://github.com/punkpeye/awesome-mcp-servers#cloud-platforms) |
## 隐私政策
docker-mcp-server不收集任何数据,不发送任何遥测数据,并且没有由作者操作的后端。 它在本地运行,仅与您指向的Docker守护进程和容器注册表通信,作为您请求的 操作的一部分。 完整的声明在[PRIVACY.md](https://github.com/L337-org/docker-mcp/blob/main/PRIVACY.md)中。
## 贡献
欢迎贡献。 该项目重视Docker SDK公共界面与我们公开的MCP工具之间的紧密映射。 有关项目布局、工具约定、新工具模块的检查清单和本地开发设置,请参见[CONTRIBUTING.md](https://github.com/L337-org/docker-mcp/blob/main/CONTRIBUTING.md)。
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器