mcpField
D
Docker MCP Server

Docker MCP Server

本地服务
github.com/GavinLucas云与基础设施92 天前更新

关于 Docker MCP Server

Docker MCP Server 为 AI Agent 提供管理和监控本地或远程 Docker 守护进程的类型化工具,并通过只读与破坏性操作限制、输出截断及日志和统计资源辅助控制。

主要功能

  1. 01管理容器、镜像、网络和卷
  2. 02管理 Swarm 服务等 Docker 域
  3. 03标记只读及破坏性操作
  4. 04通过全局模式限制写入
  5. 05以资源形式读取日志和统计

适用场景

  1. 01排查容器故障和资源使用情况
  2. 02管理本地及远程 Docker 环境
  3. 03比较测试与生产守护进程状态

MCP 相关

这是一个 MCP 服务,向 MCP 客户端提供类型化的 Docker 操作工具,以及日志、统计、SDK 文档和实时工具目录。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

暂未收录安装方式

我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。

代码仓库
安装包
pypidocker-mcp-server2.1.1
ocighcr.io/gavinlucas/docker-mcp-server:2.1.1
mcpbdocker-mcp-server-2.1.1.mcpb

工具

162

收录的工具列表 · 更新于 2 周前

参数类型必填说明
annotationsarray否
attestarray否
build_argsobject否
build_contextsobject否
builderstring否
cache_fromarray否
cache_toarray否
contextstring是
filestring否
labelsobject否
loadboolean否
no_cacheboolean否
no_cache_filterarray否
outputarray否
platformsarray否
provenancestring否
pullboolean否
pushboolean否
sbomstring否
secretarray否
ssharray否
tagsarray否
targetstring否
timeout_secondsnumber否

详细介绍

README 配图

docker-mcp-server

docker-mcp MCP server

它不仅仅是一个功能齐全的 MCP 服务,可让 AI Agent 管理 Docker(容器、镜像、网络、卷、swarm 服务、密钥、配置、节点、插件等),还可以帮助你创建工作流,轻松管理 Docker 环境。

它比直接调用 Docker CLI 提供更强的控制力和灵活性:每项操作都作为独立的类型化工具提供,并标明是否为只读操作,同时单独标记具有破坏性的操作。这意味着客户端可以自动批准读取操作,同时始终要求确认任何破坏性操作;整个服务也可以切换为只读或禁止破坏性操作模式,作为全面的安全防护。输出长度受到限制,不会无限增长——达到上限时会设置 truncated 标志,而不是悄然超出 Agent 的上下文容量。

对于简单场景,你只需安装即可使用,无需任何配置——加载后,它会自动发现本地 Docker 套接字,并向 AI Agent 提供完整的命令接口。对于高级用户,它可以管理多个 Docker 守护进程,例如在同一会话中同时管理本地开发环境和通过 TCP、TLS 或 SSH 连接的远程生产环境。你还可以将某些守护进程设为只读,从而监控它们而无需担心意外更改。

它甚至可以在未安装 Docker 的机器上运行,并通过 SSH、TLS 或 TCP 管理远程守护进程(某些功能需要 SSH)。AI 本身无需 shell 或 SSH 访问权限。

MCP 服务还会将日志和统计信息等内容作为资源提供,便于监控和排查问题,让你能够解答问题,例如“我的容器为什么崩溃了?”、“我的 swarm 状态如何?”、“我是否遇到了内存压力?”、“我的卷占用了多少磁盘空间?”、“我的测试环境和生产环境有哪些差异?”,等等……

文档是为 Agent 编写的,而不仅仅是为配置服务的人准备的:MCP 资源会在会话中提供 Docker SDK 参考文档(对于无法读取资源的客户端,也提供可通过工具调用的备用方式),实时工具目录资源则会准确报告当前配置下已注册的工具。每个工具的说明都会列出最相近的同类工具以及各自的适用场景,用通俗的语言说明前置条件和副作用,并如实说明可能导致失败的情况——因此,Agent 可以从 150 多种选项中一次就选对工具,而不必猜测。

docker-mcp-server 已针对支持延迟加载工具的新一代 MCP 客户端进行了优化。对于仍会立即加载所有工具的客户端,可以选择配置服务,排除部分领域中的工具(例如排除 swarm 和 scout 工具),以缩减工具列表。还可以将 MCP 服务设为“只读”或“禁止破坏性操作”模式,使任何具有写入或破坏性能力的工具都不会被注册,从而进一步减小占用。

此服务完全在你的机器上运行,可以选择原生运行、作为 mcpb bundle、作为 Claude 插件,或容器化运行,并且不会发送任何遥测数据。你完全掌控一切——请参阅隐私政策。

要求

注意:如果使用容器化的 MCP 服务或 MCPB 捆绑包,Python 和 uv 的要求已为你处理好。

  • 运行中的 Docker 守护进程,可供运行服务的主机访问(遵循标准的 DOCKER_HOST / Unix 套接字约定)
  • Python ≥ 3.14
  • 用于依赖管理的 uv
  • 仅限 Intel (x86_64) macOS: 原生安装(通过 uvx/pip、Claude 插件或 .mcpb 捆绑包;这些方式都会在本地解析依赖)需要 Rust 和 OpenSSL 3.x,因为 cryptography(通过 mcp -> pyjwt[crypto] 引入的传递依赖)自版本 49.0.0 起不再提供 x86_64 macOS wheel,因此必须在此平台上从源代码构建。如果不想安装构建工具链,可以改用容器镜像——它会运行相同的预构建 Linux 二进制文件,不受 Mac CPU 架构影响,因此不受此要求限制。更多信息请参阅安全注意事项。

使用服务

该服务已发布到 PyPI,名称为 docker-mcp-server。在 AI 工具的 MCP 配置中(通常是 mcp.json 或客户端中的等效配置)添加一条指向它的条目,让 uvx 运行它——uv 会在首次使用时获取并缓存该软件包:

{
  "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 安装。 若要直接运行此仓库中的未发布修订版本:

{
  "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,每个 GitHub Release 都附有一键安装捆绑包 docker-mcp-server-<version>.mcpb(以及匹配的 .sha256 文件)。下载后将其拖入设置 > 扩展,或使用设置 > 扩展 > 高级设置 > 安装扩展...并选择该文件。安装对话框会显示Docker 主机字段,以及只读/禁止破坏性操作/禁用域名开关,无需手动编辑 JSON。

这是一个 uv 类型捆绑包:Claude Desktop 托管的 uv 会解析依赖并运行服务,因此主机只需具备 Docker,无需单独安装 Python、uv 或 git。将Docker 主机字段留空即可使用默认 Docker context;设置一个端点(ssh://user@host)以连接远程守护进程,或列出多个端点(参见管理多个守护进程)。

安装为 Claude 插件

claude-plugin/ 文件夹将此服务打包为 Claude Code 和 Cowork 的插件,供 Anthropic 插件目录使用。它会运行 uvx docker-mcp-server==<version>,并固定到构建该插件时使用的发布版本,因此主机上需要安装 uv。它附带一个锁文件,按哈希固定所有依赖;该目录说明其锁定启动方式会精确安装这些依赖。通过其他方式加载时,uvx 会在安装时解析依赖。它提供与 .mcpb 安装对话框相同的设置(Docker 主机、只读、禁止破坏性操作和禁用域名),可在 Claude Code 的插件设置(/plugin)中配置。发布流水线只有在版本发布到 PyPI,且插件已从 PyPI 安装并测试后,才会更新该目录提供的插件。

作为容器运行

以容器方式运行服务,即可完全免除 Python / uv / git 前置条件——主机只需要 Docker,而你已经安装了。每次发布时都会在 Docker Hub(gavinlucas/docker-mcp-server)和 GHCR(ghcr.io/l337-org/docker-mcp-server)发布预构建的多架构镜像(linux/amd64 + linux/arm64)——两者完全相同。将 MCP 客户端指向 docker run:

{
  "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 及其插件;在 Stack 中,只有 stack_deploy 会这样做。

变体标签约略大小包含内容
full (默认):latest、:<version>~510 MBdocker CLI + compose + buildx + scout
no-scout:no-scout、:<version>-no-scout~315 MBdocker CLI + compose + buildx

Scout 的插件二进制文件本身就使 full 比 no-scout 大约多出 ~195 MB。no-scout 镜像还会将 DOCKER_MCP_SERVER_DISABLE=scout 设为默认值,因此不会注册 scout 工具——Agent 不会收到其 CLI 插件缺失的工具(它看到的是更精简、完全可用的工具列表,而不是每次调用都会报错的 scout 工具)。如需更改禁用项,可在运行时通过 -e DOCKER_MCP_SERVER_DISABLE=... 覆盖(注意,这会替换而不是追加)。

自行构建。 所有变体都通过构建参数使用仓库的 Dockerfile 构建:

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-only, ~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(无根模式:-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(或者启用 Settings > Advanced > Allow the default Docker socket,并使用 /var/run/docker.sock)。
  • Windows(Docker Desktop / WSL2): 引擎使用命名管道,而非 Unix 套接字——建议使用 -e DOCKER_HOST=tcp://host.docker.internal:2375(在 Docker Desktop 中启用 TCP 端点)。该端点未经身份验证且未加密——请确保其仅绑定到本地主机,不使用时将其禁用;对于任何远程守护进程,请使用 TLS 或 DOCKER_HOST=ssh://...。
  • 远程 / TLS / SSH 守护进程: 跳过套接字挂载,改为传入 -e DOCKER_HOST=...(以及下方的 TLS 变量)——请参阅连接远程守护进程。 访问宿主机文件系统。 在容器内,文件路径工具(image_save / container_export 中的 dest_path、image_load / container_archive_put 中的 from_file、container_archive_get_to_file, 以及 compose 的 project_dir / files)解析的路径位于容器内, 而非宿主机上。请绑定挂载要用于交换文件的目录——使用内外相同的 路径,可使宿主机和容器中的路径保持一致:
-v $HOME/docker-work:$HOME/docker-work

如果使用这些工具之一时指定的路径不在绑定挂载中,服务会立即拒绝操作,并告知你需要添加哪个 -v——否则,写入未映射路径的内容会在容器退出时被静默丢弃。(上限为 32 MiB 的带内字节工具无需挂载。)配置环境变量(DOCKER_MCP_SERVER_READONLY、DOCKER_HOST 等)应像 uvx 安装时一样,放在客户端的 env 块中。

连接远程守护进程

设置 DOCKER_HOST 后,服务会直接使用它(通过 docker.from_env(),因此也会遵循 DOCKER_TLS_VERIFY / DOCKER_CERT_PATH)。通过 env 设置常见覆盖项:

"env": {
  "DOCKER_HOST": "tcp://remote-host:2375",
  "DOCKER_TLS_VERIFY": "1",
  "DOCKER_CERT_PATH": "/path/to/certs"
}

默认守护进程(未设置 DOCKER_HOST)。 未设置 DOCKER_HOST 时,服务会像 docker CLI 一样解析守护进程,而不是假定其位于 /var/run/docker.sock:它会遵循当前启用的 Docker 上下文(DOCKER_CONTEXT,否则读取 ~/.docker/config.json 中的 currentContext,并从该上下文的 meta.json 中读取端点);如果没有解析到端点,则会探测常见的套接字位置(Docker Desktop 4.13+ 的 ~/.docker/run/docker.sock、无根模式的 $XDG_RUNTIME_DIR/docker.sock,然后是 /var/run/docker.sock)。这很重要,因为单独使用 docker.from_env() 会忽略上下文并回退到 /var/run/docker.sock——而 Docker Desktop 4.13+ 默认不再创建该套接字(它使用 desktop-linux 上下文,除非你启用 Settings > Advanced > Allow the default Docker socket),因此,通过 CLI 可访问的标准 Desktop 安装在此处会失败。优先级如下:非空的 DOCKER_HOST 始终优先,并直接交由 docker.from_env() 处理(该函数会忽略上下文);仅当未设置 DOCKER_HOST 时才会查询 DOCKER_CONTEXT / currentContext;只有两者都未解析到端点时才会探测套接字。远程上下文附带的 TLS 材料不会自动应用——tcp:// + TLS 上下文仍需设置 DOCKER_HOST / DOCKER_CERT_PATH。

通过 SSH

通过纯 Python 传输方式支持 DOCKER_HOST=ssh://user@remote-host(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,因为这会信任返回的任何密钥(包括中间人攻击者提供的密钥)。
  • 在容器中。 以只读方式挂载 SSH 文件——-v $HOME/.ssh:/root/.ssh:ro(密钥 + known_hosts)——或转发代理套接字;无需挂载套接字,也无需安装 ssh 软件包。

由 CLI 驱动的工具(Compose、Stack、Buildx、Scout、Context)会调用 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 二进制文件,在主机上安装和在容器镜像中运行时效果也完全相同。唯一例外是 ~/.ssh/config 中的 ProxyCommand(堡垒机/跳板机场景):paramiko 会按原样执行该命令,而该命令通常是 ssh -W %h:%p ...,因此跳板机连接仍会调用系统的 ssh 客户端,尽管直接连接不会。

这个临时的 127.0.0.1 监听器会在单次 CLI 调用期间,使用你的 SSH 凭据连接到远程(等同于 root 权限的)守护进程,因此在这段短暂的时间内,任何共享同一环回接口的进程都可以访问它。暴露范围有限——仅限本地主机,调用返回后即会关闭——而在容器中范围更小,只能由该容器网络命名空间内的进程访问。无论哪种情况,信任边界仍然是守护进程(请参阅安全注意事项)。

未安装本地 Docker

如果本地未安装 Docker,或者缺少调用所需的插件,大多数工具仍会像以前一样在远程主机上运行。少数工具系列(Compose、Buildx、Scout 和 stack_deploy)会通过 SSH 直接在目标主机上运行。如果本地未安装 Docker,这些命令无法通过 TCP 和 TLS 连接运行。

值得注意:

  • 这是备用方案,而非首选方案。 只要本地 CLI 能处理该调用——包括二进制文件和调用所需的插件——就始终会使用本地 CLI,因此正常安装不会有任何变化。
  • 命令读取的本地文件会先复制到远程主机——包括 Compose 项目目录、bake 文件和构建上下文(遵循 .dockerignore)——放入私有的 0700 临时目录中,并在调用返回时删除。但这只是尽力而为,因为 SSH 连接中断后,便无人能执行清理。未清理的目录名为 docker-mcp-server.stage.*,并会记录相关故障。
  • 使用远程主机的凭据。 注册表登录信息来自远程主机的 ~/.docker/config.json,因此,访问私有注册表的 compose_pull、stack deploy --with-registry-auth 或大多数 Scout 操作可能需要先在远程主机上运行 docker login。system_login 会与守护进程通信,不会写入远程 CLI 的配置。
  • 整个工作目录都会被复制,因为无法确定 Compose 文件引用了哪些文件(build:、env_file:、include: 都可以指向任意路径)。请将工具指向项目目录,而不是较大的父目录;否则调用会因大小限制而被拒绝(200 MiB / 50 000 个条目)。
  • compose_cp 会通过同一 SSH 连接中转位于本地一侧的复制对象:主机上的源文件会像其他输入一样先暂存到远程主机;容器中的结果则会在复制成功后取回真实目标位置。实际复制仍会通过远程主机上的真实 docker compose cp 执行,因此所有参数的行为与本地执行时相同。唯一的区别是:如果本地目标已存在,容器到主机的复制会被拒绝,因为只有本地主机知道这一点。
  • 少数情况会直接拒绝执行,而不会只完成一部分:对于 buildx_build,如果 output/cache_to 中包含文件系统 dest=、cache_from 中包含本地 src=,或包含任何 ssh=,调用都会被拒绝——这些内容会在远程机器上解析。
  • 远程主机必须提供 POSIX shell。 任何 Linux/macOS/BSD 主机都符合要求,在 WSL 发行版内运行的 sshd 也受支持(它是 Linux 目标主机;并且使用 Docker Desktop 的 WSL2 后端时,守护进程本来就在其中)。如果 sshd 运行在 Windows 侧的 cmd/PowerShell 中,则会附带说明性错误并拒绝执行;来自 MSYS/MinGW/Cygwin 的 uname 也会被拒绝。Windows 方言虽已纳入架构设计,但尚未实现。若 Windows sshd 的 shell 是 wsl.exe,命令会在 WSL 中运行,但其 SFTP 子系统仍在 Windows 侧运行,因此文件复制工具会被拒绝;仅运行命令的工具仍可使用。
  • context_* 工具绝不会回退到远程执行。 它们管理的是此主机的 CLI 上下文注册表,远程主机对此一无所知。
管理多个守护进程

以上内容都针对单个守护进程。要在单个会话中管理多个守护进程——例如本地开发环境和远程生产环境——请将 DOCKER_MCP_SERVER_HOSTS 设置为以逗号分隔的 name=endpoint 列表:

"env": {
  "DOCKER_MCP_SERVER_HOSTS": "local=auto, prod=ssh://[email protected](ro)"
}
  • endpoint 可以是 auto(如上文所述,使用默认上下文/套接字)、local(使用平台本地套接字,忽略上下文),也可以是 unix://、tcp://、ssh:// 或 npipe:// URL。推荐使用 ssh:// 作为远程传输方式(每台主机通过 SSH 密钥进行身份验证,无需配置 TLS 证书)。通过 TLS 连接的 tcp:// 守护进程需要使用 (tls=<dir>) 标记指定证书目录,例如 prod=tcp://prod:2376(tls=/etc/docker/prod)。该目录必须包含 ca.pem(始终使用它验证守护进程,因此自签名守护进程也能正常工作,只需在此固定其证书);仅当守护进程要求客户端证书(双向 TLS)时,才添加 cert.pem 和 key.pem。不支持未经验证的 TLS 模式——TLS 连接始终会对守护进程进行身份验证,因此加密始终伴随验证。
  • 在端点后添加 (ro) 可将该主机标记为只读:更改类和破坏性工具会拒绝对其执行操作。这项逐主机保护在调用时强制执行,独立于服务器级 DOCKER_MCP_SERVER_READONLY 开关——将生产环境标记为 (ro) 后,Agent 可以随时检查它,但无法更改它,而本地环境仍可读写。
  • (nd) 会将主机标记为非破坏性:只有破坏性工具(删除、清理、终止)会拒绝对其执行操作——读取和常规更改(启动/停止/创建)仍可执行。这与服务器级 DOCKER_MCP_SERVER_NO_DESTRUCTIVE 开关作用相同,但按主机生效。(ro) 已包含此限制,因此 (ro)(nd) 可以组合使用,不会报错,但属于冗余设置。
  • 单个守护进程的简写。 不含 name= 的纯值表示单个主机——DOCKER_MCP_SERVER_HOSTS=ssh://ops@prod(也可以是 auto 或留空)。因此,这个字段也适用于单个远程主机的情况。未设置 DOCKER_MCP_SERVER_HOSTS 时,DOCKER_HOST 仍然有效;但设置 DOCKER_MCP_SERVER_HOSTS 后,它将接管配置(此时会忽略 DOCKER_HOST,并向 stderr 输出一次提示)。

Agent 如何使用它。 配置两个或更多主机后,每个面向守护进程的工具都会增加可选的 host 参数,其值限定为已配置的名称:省略该参数时,只读工具默认使用第一个主机,而更改类和破坏性工具则必须显式指定 host(以免 Agent 意外更改错误的守护进程)。host_list(以及 docker-mcp://hosts 资源)会报告已配置的主机及默认主机;容器/服务可观测性资源也会支持指定主机——默认主机的日志尾流 URI 为 docker-logs:///{id}(注意 authority 为空),命名主机的 URI 为 docker-logs://{host}/{id};docker-stats://、service-logs:// 和 service-tasks:// 也遵循相同模式;配置多个主机后,不再注册单主机的简写形式(docker-logs://{id} 等)。survey_hosts 提示词会以只读方式遍历所有主机。auto/local 端点会解析为具体 URL,并在启动时固定,因此 SDK 和 CLI 始终会将名称解析到同一个守护进程——更改 Docker 上下文后,请重启以重新解析。

Agent 可以做什么

加载后,Agent 会获得按 Docker 领域分组的 MCP 工具。以下是几个示例:

  • 容器 - container_run、container_list(设置 managed_only=True 只列出由此服务创建的容器 - 请参阅来源标签)、container_exec、container_logs、container_stop、container_commit、container_export / container_archive_get_to_file / container_archive_put(在主机路径与容器之间流式传输 tar 归档)
  • 镜像 - image_build、image_pull、image_push、image_tag、image_prune(设置 build_cache=True,也会清理守护进程的构建缓存 - 这是独立于悬空镜像的资源)、image_save / image_load(通过 dest_path / from_file 在主机路径与镜像之间流式传输镜像 tar 包)、image_import(从扁平 rootfs tar 包、URL 或现有镜像构建单层镜像 - 即 docker import,不要与 image_load 混淆)
  • 插件 - plugin_install(从注册表拉取;安装前设置 dry_run=True 可查看插件要求的主机访问权限 ,守护进程会以非交互方式授予这些权限)、plugin_enable / plugin_disable、plugin_configure、plugin_upgrade(同样支持 dry_run)、plugin_list / plugin_inspect、plugin_remove (管理引擎插件 - 卷、网络、日志驱动程序 - 而非用于扩展 docker 命令本身的 CLI 插件)
  • 网络 / 卷 - network_create、network_connect、volume_create、volume_prune
  • Swarm - swarm_init、swarm_join_tokens(完成从初始化到加入集群的流程)、swarm_update(轮换加入令牌 / 解锁密钥)、service_create、service_scale、service_rollback(重新应用上一个服务规范)、service_ps(查看单个服务的任务;不指定服务则查看集群中的所有任务,可按节点或期望状态筛选 - 没有任何单条 CLI 命令能做到这一点)、service_logs(查看服务的日志,或单个任务的日志)、node_list、node_remove、secret_create、config_create
  • 系统 - system_wait(统一的等待工具:等待容器退出、变为健康状态或输出某行日志;等待服务或堆栈收敛、堆栈移除、节点就绪、Compose 项目运行、变为健康状态或退出,或等待标签推送到注册表 - 每次等待都有超时,默认 600 s;超时会返回结果而非抛出异常)、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 (封装 docker compose CLI 插件)
  • 堆栈 - stack_deploy、stack_list、stack_ps、stack_services、stack_remove (将 Compose 文件部署到 Swarm 中作为堆栈 - stack_deploy 封装 docker stack deploy,该命令会转换 Compose 文件;其余工具使用 Engine API - 需要 Swarm 管理器)
  • 上下文 - context_list、context_inspect、context_create、context_use、context_remove (封装 docker context CLI)
  • 注册表 / Hub - registry_tags、registry_manifest、registry_image_config(读取镜像的 env / entrypoint / labels,无需拉取镜像)、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 插件;除 scout_sbom 外,使用其他工具都需要在运行 CLI 的主机上执行 docker login)。 基于 SDK 的功能表面与 Docker SDK 参考保持一致——其中记录的内容在这里都可用。Compose 和 Context 功能表面遵循 Compose CLI 和 docker context 参考文档。

该服务还会将 Docker SDK for Python 参考文档以及精选的 Docker CLI / registry 参考文档发布为 MCP 资源,供 Agent 在运行时查阅:读取 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 列出该服务了解的所有工具,包括其所属领域、变更类别以及是否由当前配置注册,可用于确认某个工具的影响范围,或了解该工具为何未出现在当前列表中。无法读取资源的客户端可使用 tool_list 工具获取相同内容,该工具还支持筛选:使用 tool_list(domain="buildx") 获取某个领域中每个工具占一行的简介,使用 tool_list(category="destructive") 查看可能破坏数据的工具,或使用 tool_list(keyword="logs one task") 搜索名称、摘要和参数名称——所有匹配任意关键词的工具都会返回,匹配词最多的排在前面。该工具仅列出当前配置注册的工具;如果没有匹配项,则会明确返回空结果。与 docs_lookup 一样,无论 DOCKER_MCP_SERVER_DISABLE 的值如何,该工具始终可用。

容器和服务的可观测性也以资源形式提供,因此客户端无需调用工具即可附加实时状态作为上下文:docker-logs://<id-or-name> 用于获取容器日志的有限尾部(容器退出后仍可读取,便于诊断原因),docker-stats://<id-or-name> 用于获取运行中容器的资源使用情况汇总(CPU 百分比、内存、网络和块 I/O)。Swarm 服务也采用相同模式——service-logs://<id-or-name> 用于获取有限的日志尾部,service-tasks://<id-or-name> 用于获取计算得出的任务 / 滚动更新摘要(运行中与期望的任务数量、失败任务以及当前滚动更新状态)。使用 container_list / service_list 查找要填入的 ID 或名称。这些资源与对应工具(container_logs/container_stats、service_logs)互为补充;禁用 services 时,服务相关资源会隐藏(containers 则不会)。

示例提示词

许多 AI 客户端允许你直接调用已注册的 MCP 提示词(在 Claude Code 中,输入 / 即可查看)。该服务在 docker_mcp/tools/prompts.py 中提供了一小套模板,用于搭建多步骤工作流——模板会生成结构化计划,然后由 Agent 使用 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 行日志,检查其状态和退出代码,并在更改任何内容之前告诉我问题所在。 将正在运行的 web 容器替换为 nginx:1.27,同时保留其当前端口、挂载和重启策略。 规划一个位于私有网络上的 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_* 别名拼写现已不再受支持。

若要选择服务连接的守护进程,请参阅连接远程守护进程和管理多个守护进程(DOCKER_MCP_SERVER_HOSTS / DOCKER_HOST)。以下变量用于限制注册的工具。

服务启动时,三个环境变量会限制注册的工具。由于这些变量会在注册时移除工具,被禁用的工具绝不会出现在客户端的工具列表中——这是服务端的保证,而不是客户端提示词。将两个布尔开关设为 1 / true / yes / on:

  • DOCKER_MCP_SERVER_READONLY - 仅注册只读工具(查询、日志/数据读取、扫描)。所有会更改状态的工具都会被省略。适用于不得修改任何内容的监控或检查 Agent。
  • 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 会精简 Agent 永远不会用到的构建/扫描工具。领域是工具模块的名称:images、networks、volumes、compose、stack、context、buildx、scout、registry、swarm、services、nodes、plugins、configs、secrets。不能禁用 system 和 containers,因此指定任一名称都会被忽略:system 包含 Agent 用于了解当前状态和恢复所需的内容,以及唯一的等待工具;containers 则是 Docker 服务的核心,compose、stack 和 service 工具启动的容器只能通过它来等待、读取和移除。禁用 containers 并不能阻止 Agent 运行代码,因为 compose、stack、service_create 和 image_build 都能运行代码;真正能做到这一点的是 DOCKER_MCP_SERVER_READONLY,而且它还会阻止 Agent 登录注册表。禁用某个领域也会将其中的目标从 system_wait 中移除。名称不区分大小写;无法识别的名称不会禁用任何内容。两种错误都会通过三种方式报告,因为 MCP 客户端很少会向任何人显示服务的 stderr:启动时在 stderr 中输出一行 WARNING,在 tool_list 的结果中添加 configuration_warnings 条目(并在工具目录中添加 unknown_disabled_domains/ignored_disabled_domains),以及在服务说明顶部添加一行,告知 Agent 检查 tool_list 并告知用户。此设置可与类别开关叠加:只有类别未被禁用且所属领域已启用的工具才会注册。禁用某个领域移除的不仅是其工具:对应的工作流提示词也会跳过(这样 Agent 就不会收到驱动服务器已不再提供的功能区域的提示词——例如,禁用 scout 会移除 audit_image_cves 提示词,否则该提示词会指示 Agent 调用一个未注册的工具),对应的文档资源也会从 docker-docs://contents 中隐藏(例如 scout/scout-cli 章节)。工具目录中的 prompts 列表和 disabled_doc_sections 字段可用于审计这两项变更。精简 Agent 不需要的领域,也能缩小客户端需要处理的工具列表;对于这么大规模的服务来说,这一点很重要。 这三项都不是网络控制措施。 DOCKER_MCP_SERVER_READONLY 限制的是 Agent 能更改什么,而不是服务能访问什么:注册表和 Hub 工具是只读的,因此即使是只读服务,也仍会向工具参数指定的注册表主机发起出站 HTTPS 请求——请求从服务运行所在的位置发出,而该位置的网络访问范围可能比它所管理的守护进程更广。除非注册表返回令牌质询,否则这些请求不会携带凭据;含凭据的令牌端点会先经过验证(方案、不得向公共主机发送明文,以及公共注册表不得将其 realm 指向私有地址或环回地址),但请求仍会发出,响应也会返回给 Agent。docs_lookup 和 docker-docs:// 资源同样会从固定列表中的文档主机获取内容。如果你需要阻止出站请求,DOCKER_MCP_SERVER_DISABLE=registry 会彻底移除该域;对于其余请求,则应通过主机上的网络策略进行控制——完整的服务访问目标列表见 PRIVACY.md。

此外,每个已注册工具都带有 MCP ToolAnnotations——查询工具带有 readOnlyHint,破坏性操作带有 destructiveHint(prune 系列还带有 idempotentHint)——因此,Claude Code 这类客户端可以自动允许安全的读取操作,并对破坏性调用进行限制。分类信息位于 docker_mcp/server.py 中的 TOOL_CATEGORIES。如需在运行时查看完整信息——包括每个工具所属的域、类别,以及当前启用的开关是否注册了该工具——请读取 docker-mcp://tool-catalog MCP 资源。

对于私有注册表,如果没有传入显式的 username/password 参数,基于 HTTPS 的 registry_* 工具会回退到服务环境中的 DOCKER_MCP_SERVER_REGISTRY_USERNAME / DOCKER_MCP_SERVER_REGISTRY_PASSWORD(显式参数优先;只有两个参数都未设置时才会使用环境变量)。在环境中设置凭据可避免它们出现在工具参数中,因为许多 MCP 客户端会原样记录这些参数——密码可以是个人访问令牌。

来源标签

Agent 通过此服务创建的每个 Docker 对象——容器、网络、卷、swarm 服务、配置和密钥——都会带上一组 docker-mcp-server.* 标签,记录该对象由此服务创建(docker-mcp-server.managed=true)、服务版本、来源工具和创建时间戳。这样,你(或清理任务)之后就能通过单条命令 docker ... --filter label=docker-mcp-server.managed=true,准确列出 Agent 创建的所有对象;container_list、network_list、volume_list 和 service_list 中的 managed_only=True 参数提供了工具内的快捷方式(它会与传入的其他 filters 组合使用)。标签只会附加,不会覆盖:如果发生键冲突,你自行传入的标签始终优先;标签使用独立命名空间,因此默认情况下是安全的;DOCKER_MCP_SERVER_NO_LABELS=1 可彻底关闭标签功能。镜像构建不会添加标签,这是有意为之,因为构建标签会改变生成镜像的摘要。

若要仅清理此服务创建的内容——而不触及其他内容——请使用 prune_managed 工作流提示词;它会将每个移除步骤限定为 docker-mcp-server.managed=true 标签对应的对象(只有传入 include_volumes=True 时才会清理卷,并且仅在确认后进行)。

示例:只读监控服务

这些内容都应放在 MCP 客户端配置中该服务条目的 env 块内(与上文的 DOCKER_HOST 位于同一位置)。例如,针对远程守护进程的只读检查服务:

{
  "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)时,对应配置如下:

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

或者完全不用服务:l337-docker Agent 技能

关于任何 MCP 服务,一个合理的问题是:它是否有必要存在。本仓库公开给出了答案:skills/l337-docker/ 是一项 Claude Code Agent 技能,仅通过 docker CLI 操作 Docker——无需服务进程、无需 Python,除了 docker 二进制文件外什么都不需要(少数注册表操作示例还需要 jq 和 curl)。

这项技能的存在,是为了如实展示技能方案的能力上限,让你自行权衡取舍,而不是听信我们的一面之词。它力求将这种方案做到最好:由路由器和各领域的参考资料及工作流组成,每条命令都经过真实守护进程验证,Shell 片段也由 CI 执行,确保不会偏离实际情况。对于单个本地守护进程和日常工作,它很可能已足够——如果是这样,就用它。

它的局限不在覆盖范围,而在于强制执行。技能的安全规则只是提示词中的指示;服务的安全规则则是代码中的拒绝机制:

MCP 服务l337-docker 技能
只读/禁止破坏性操作模式强制执行——永远不会注册这些工具写明规则,要求 Agent 遵守
按守护进程设置写入保护((ro)/(nd))在调用边界强制执行不支持
自终止防护强制执行写明规则
输出长度限制强制执行,并带有 truncated 标记写明规则(--tail、--no-stream)
多守护进程定向启动时解析并固定目标使用可能在会话中途改变的环境 Docker 上下文
要求Python ≥3.14,或容器docker 二进制文件

这种差异在最容易被忽视的地方最为重要:提示词中的规则可能在压力下被跳过,也可能被 Agent 刚读过的容器日志中的提示注入绕过。未注册的工具根本无法调用。因此,对于任何面向生产环境的操作,或任何需要保证而非指示的场景,都应优先选择服务;而在风险较低、简单性更重要时,则优先选择技能。

MCP_VS_SKILLS.md 提供了完整、坦诚的对比:两者经过测量的令牌开销——对于积极加载的客户端,技能便宜得多,尤其是在空闲时;而对于按需加载的客户端,服务的单项任务开销更低——此外还介绍了各自真正擅长的方面,以及涵盖每项工具、提示词和资源的逐工具对照表。

要安装,请从某个发布版本下载归档文件,并解压到技能目录中。归档以 l337-docker/ 为根目录,因此无需调整即可正确放置:

# personal (all projects)
tar -xzf l337-docker-skill-<version>.tar.gz -C ~/.claude/skills
# or per-project, checked into version control
tar -xzf l337-docker-skill-<version>.tar.gz -C .claude/skills

使用随附的校验和验证(sha256sum -c l337-docker-skill-<version>.tar.gz.sha256);该归档可逐字节重现,因此从标签重新构建会得到相同的哈希值。技能和服务可以共存——它们为自己创建的资源使用不同标签,彼此也不会读取对方的资源。

安全注意事项

将此服务连接到 AI Agent,相当于授予它对已配置守护进程与本地 Docker CLI 会话相同级别的访问权限。这种权限范围很广:守护进程的套接字实际上等同于运行它的主机上的 root 权限。请将 Agent 视为特权用户,并在启用服务前权衡以下风险。

  • 使用受限范围的守护进程。 优先将 DOCKER_HOST 指向专供 Agent 操作其获准管理工作负载的守护进程(开发 VM、远程沙箱、Docker Desktop、无 root 安装),而不是生产环境的套接字。守护进程就是信任边界——没有针对单个工具的授权层。
  • 以容器方式运行。 将 /var/run/docker.sock 挂载到容器中,赋予它与 uvx 安装相同的、相当于 root 的守护进程访问权限——不多也不少,只是现在在 docker run 命令中明确写出。同样适用受限守护进程的建议:优先挂载获准由 Agent 控制的守护进程套接字,或将 DOCKER_HOST 指向该守护进程。请注意,容器化后,文件路径工具读写的是容器自身的文件系统,因此只能访问通过绑定挂载提供的主机目录(参见以容器方式运行)。作为防误操作措施,具有破坏性的容器生命周期工具(container_remove、container_kill、container_stop、container_restart、container_pause)拒绝操作服务自身所在的容器,避免 Agent 在调用过程中结束自己的会话;这只是便利措施,不是安全边界(可通过 DOCKER_MCP_SERVER_ALLOW_SELF_TERMINATE=1 绕过,而且人类始终可以从主机 shell 恢复该容器),也不会限制拥有守护进程权限的 Agent 以其他许多方式影响主机。
  • 特权容器和主机挂载。 container_run 接受 privileged=True 和任意 volumes。特权容器,或绑定挂载主机 / 的容器,都能轻易逃逸到主机文件系统。除非已审查请求,否则不要允许 Agent 设置这些选项。Compose 文件也可以声明相同设置——在陌生项目上批准 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 则会丢弃客户端并清除缓存。守护进程端没有可结束的会话——Engine 的 /auth 端点只负责验证。
    • 基于 HTTPS 的注册表工具(registry_tags、registry_manifest、registry_image_config、hub_tags、hub_repo_info、hub_rate_limit,以及用于注册表标签的 system_wait)会直接通过 HTTPS 与注册表通信,不会读取 ~/.docker/config.json。registry_* 工具可通过 username / password 访问私有注册表;更好的做法是从服务的环境中读取 DOCKER_MCP_SERVER_REGISTRY_USERNAME / DOCKER_MCP_SERVER_REGISTRY_PASSWORD,这样凭据就不会经过工具参数(参见配置);hub_* 工具仅支持公开的 Hub 仓库。如果要通过参数传递凭据,请使用每次调用专用且权限范围最小的令牌,而不是长期有效的密码。注册表返回 Bearer 身份验证质询时,服务会在发送任何内容前验证其指向的令牌 realm:协议必须为 http/https,拒绝向非本地主机使用明文 http;公开注册表也不得将带凭据的令牌请求重定向到私有/环回地址(防止 SSRF)。真正的本地开发注册表(例如 localhost:5000)仍可使用本地 realm。分页也采用相同限制:Docker Hub 的 next URL 必须保持在 Hub 自身的源站上;OCI Link 标头中的主机名会被丢弃,改用当前查询的注册表,因此响应正文绝不可能将此服务重定向到任意主机。重定向本身允许跨主机跟随——注册表通常会将 blob 获取请求重定向到其他主机上的 CDN——但 HTTP 客户端会在任何跨源重定向时剥除 Authorization 标头,因此凭据不会随之传递。
  • 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(在集群中拥有相当于 root 的权限)。对于任何会记录工具流量的客户端,都应将这些内容视为已暴露;最好在主机上以带外方式配置 Swarm 秘密信息并读取加入令牌,而不要经由 Agent。如果 Agent 无需接纳节点,可通过 DOCKER_MCP_SERVER_DISABLE=swarm 禁用整个功能范围(参见配置)。
  • container_exec、compose_exec 和 compose_run 会运行任意命令。 如果命令的任何部分来自 Agent 控制的输入,请使用不会调用 shell 的 exec 形式 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、image_import 和 container_archive_put(使用 from_file 时)会读取主机路径;compose_cp 会在服务容器与主机路径之间双向复制。image_import(from_url=...) 是唯一完全不经过主机的工具:守护进程会在其自身网络命名空间中获取调用方指定的 URL,因此可以访问该守护进程可访问的任何内容(与 image_pull 的注册表参数一样,由调用方指定目标)。这些工具以服务运行用户的身份执行,因此 Agent 可以写入该用户可写的任何文件,也可以读取该用户可读的任何文件。如果不信任 Agent 访问主机文件系统,优先使用带内字节工具(上限为 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 提示词也会要求 Agent 在清理卷前进行确认——但服务本身不会拦截工具调用。要实现强制保证,请使用 DOCKER_MCP_SERVER_NO_DESTRUCTIVE=1(完全移除这些工具)或 DOCKER_MCP_SERVER_READONLY=1(参见配置);如需审批步骤,请在 MCP 客户端中配置。
  • CLI shell 调用攻击面。 Compose、Stack、Buildx、Scout 和 Context 工具会在运行此 MCP 服务的主机上启动 docker 子进程。每次调用都将参数作为列表传递(不使用 shell,也不解释元字符),通过 shutil.which 查找可执行文件,并在经过清理的环境中运行(仅保留 DOCKER_HOST 及相关变量)。位置参数(镜像引用、服务 / context / builder 名称、构建上下文、bake 目标)还会在以 - 开头时被拒绝,以免将参数伪装成 CLI 标志(例如将服务命名为 --output=...);唯一的特意例外是 compose_exec / compose_run 中尾随的命令,它本就用于传入任意 argv。提供给 compose_* 的文件系统路径(project_dir、files)会由服务主机上的 docker CLI 读取——传入陌生路径可能暴露服务用户可读取的任何 Compose 文件。如果主机上没有本地 docker CLI,且目标为 ssh://,这些子进程会改在远程主机上运行(见上文),这会带来两项变化:命令以远程 SSH 用户的身份及其注册表凭据执行;命令要读取的文件会先复制到该主机的临时目录中——因此,buildx_build 的 --secret src= 文件或暂存目录中的任何其他内容都会短暂存于远程磁盘上(权限模式为 0700,调用返回时删除;只有连接中断才可能使文件残留)。对于依赖暂存的工具,请仅指定你愿意复制的目录。
  • 守护进程集合在启动时固定;请谨慎选择。 未设置 DOCKER_HOST / DOCKER_MCP_SERVER_HOSTS 时,服务的初始 SDK 连接会跟随当前 Docker context(DOCKER_CONTEXT / currentContext)——也就是 docker CLI 使用的同一守护进程。因此,如果该 context 指向远程或生产环境的守护进程,Agent 也会连接到那里。请在启动服务前设置 DOCKER_MCP_SERVER_HOSTS(或 DOCKER_HOST,或选择受限 context),以明确固定目标;使用 DOCKER_MCP_SERVER_HOSTS 时,auto / local 端点会在启动时固定,之后即使 context 发生变化也不会漂移。启动后,context_use 只会更改后续基于 CLI 的工具所用的 CLI 默认值;基于 SDK 的工具仍会使用其连接池客户端已连接的守护进程。运行时无法向任意端点引入或重新指定守护进程——system_reconnect 只能重建已配置主机的客户端(用于恢复失效连接),不能将其指向其他位置;要添加或更改守护进程,请编辑 DOCKER_MCP_SERVER_HOSTS 并重启。这一设计有意封闭了扩大信任范围的途径(Agent 无法在会话中途将相当于 root 的边界转移到未经审查的端点)。context_create(skip_tls_verify=True) 会禁用该 context 的 TLS 验证;仅用于可信的本地守护进程。
  • 每主机只读是防误操作措施,不是安全边界。 在 DOCKER_MCP_SERVER_HOSTS 中标记为 (ro) 的主机会在调用时拒绝执行会修改或造成破坏的工具(多个主机时,写操作还必须明确指定目标主机——避免 Agent 因遗漏指定目标而修改错误的守护进程)。与 guard_not_self 一样,这是进程内的便利措施:它会限制 Agent 通过此服务执行操作,但守护进程本身仍是信任边界。因此,对于 Agent 绝不能修改的主机,应优先将其指向真正只读或受限的守护进程,而不要只依赖该标记。
  • 每主机的非破坏性限制也是防误操作措施,作用范围更窄。 标记为 (nd) 的主机只会拒绝破坏性工具调用(终止、移除、清理),读取和常规修改仍会执行。与 (ro) 一样,这是由本服务防护机制在进程内执行的便利措施,并非守护进程层面的边界。
  • cryptography(通过 mcp -> pyjwt[crypto] 引入的传递依赖)自 49.0.0 起就不再提供 x86_64/universal2 macOS wheel——已确认是永久变化,并非暂时问题——因此在该平台上原生安装(使用 uvx、pip 或 .mcpb 包)会解析到当前版本并从源代码构建,需要安装 Rust 和 OpenSSL 3.x。 本项目曾短暂尝试使用仅针对 Intel macOS 的 cryptography<49 限制来避免构建步骤;后来发现该限制会影响所有平台,而不只是它指定的平台(仅设置平台范围的版本上限不会让 uv lock 分叉解析),因此所有人都被悄然固定在某个版本上,而该版本落入了后来出现的高危 CVE 影响范围(PKCS#7 EnvelopedData 解密 Bleichenbacher oracle)。项目最终移除了这一限制,而没有用其他方案替代:本项目本身不会解密 PKCS#7 信封,但明知某个依赖含有可利用的缺陷,就不应仅为了让一个平台只安装 wheel 而继续发布该依赖。如果不想安装构建工具链,请改用容器镜像(集中在 Linux 上构建,因此不会遇到此问题)。

软件包和列表

渠道链接
PyPIdocker-mcp-server
GHCR(容器)ghcr.io/l337-org/docker-mcp-server
Docker Hub(容器)gavinlucas/docker-mcp-server
桌面扩展(.mcpb)GitHub Releases
l337-docker Agent 技能(.tar.gz)GitHub Releases
官方 MCP 注册表io.github.L337-org/docker-mcp-server
Glamadocker-mcp-server
mcp.sodocker-mcp-server
awesome-mcp-serverspunkpeye/awesome-mcp-servers

隐私政策

docker-mcp-server 不收集数据、不发送遥测信息,也没有由作者运营的后端。它在本地运行,只与你指定的 Docker 守护进程和容器注册表通信,以执行你请求的操作。完整声明请参阅 PRIVACY.md。

贡献

欢迎贡献。本项目重视 Docker SDK 公共接口与我们公开的 MCP 工具之间的紧密映射。有关项目结构、工具约定、添加新工具模块的检查清单以及本地开发设置,请参阅 CONTRIBUTING.md。

商标

docker-mcp-server 是一个独立的开源项目。它与 Docker, Inc. 无关联,未获其认可,也未受其赞助。Docker 是 Docker, Inc. 的商标或注册商标。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。