Testcontainers Java 的 Docker MCP Gateway 模块:在测试中启动 MCP 网关容器
2026/9/16 15:25:46 网站建设 项目流程

Testcontainers Java 的 Docker MCP Gateway 模块:在测试中启动 MCP 网关容器

【免费下载链接】testcontainers-javaTestcontainers is a Java library that supports JUnit tests, providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container.项目地址: https://gitcode.com/GitHub_Trending/te/testcontainers-java

导读

本文讲解 Testcontainers for Java 提供的DockerMcpGatewayContainer模块,它允许你在 JUnit 测试中以真实 Docker 容器的方式启动 Docker MCP Gateway,将各种 MCP(Model Context Protocol)服务器聚合到一个统一的 SSE 端点下,供测试代码通过 HTTP 调用。读完本文,你将掌握:如何引入依赖、如何在任意 Java 应用中启动网关容器、如何注册 MCP 服务器并选择暴露的工具、如何注入密钥(secrets)、如何获取网关端点地址,以及容器底层是如何完成启动与就绪检测的。

模块概览

DockerMcpGatewayContainer是 Testcontainers 核心库(org.testcontainers:testcontainers)内置的一个专用容器类,其实现位于 core/src/main/java/org/testcontainers/containers/DockerMcpGatewayContainer.java。它继承自GenericContainer<DockerMcpGatewayContainer>,因此具备 Testcontainers 通用的生命周期管理能力(start()stop()、try-with-resources 自动关闭等)。

从源码看,该模块有几个关键默认值:

  • 默认镜像:docker/mcp-gateway(见 DockerMcpGatewayContainer.java);
  • 默认暴露端口:8811(见 DockerMcpGatewayContainer.java);
  • 默认以 SSE 传输模式启动:--transport=sse(见 DockerMcpGatewayContainer.java);
  • 自动将宿主机 Docker 套接字挂载到容器内的/var/run/docker.sock,使网关能够通过 Docker 发现本地 MCP 服务器(见 DockerMcpGatewayContainer.java);
  • 启动就绪条件:等待容器日志中出现.*Start sse server on port.*(见 DockerMcpGatewayContainer.java)。

注意:由于该模块会挂载宿主机 Docker 套接字,请仅在受信任的测试/开发环境中使用,并留意镜像docker/mcp-gateway的版本行为(测试中通常使用docker/mcp-gateway:latest,生产化测试建议固定具体版本号)。

使用示例

你可以从任意 Java 应用中通过如下方式启动一个 Docker MCP Gateway 容器实例:

DockerMcpGatewayContainer gateway = new DockerMcpGatewayContainer("docker/mcp-gateway:latest"); gateway.start();

上面的示例取自 core/src/test/java/org/testcontainers/containers/DockerMcpGatewayContainerTest.java,测试通过gateway.isRunning()验证容器确实成功启动。

更完整的典型用法是:创建容器后链式调用withServer(...)注册 MCP 服务器,并通过withSecret(...)/withSecrets(...)注入各服务器所需的 API Key 等机密信息,然后启动容器:

try ( DockerMcpGatewayContainer gateway = new DockerMcpGatewayContainer("docker/mcp-gateway:latest") .withServer("curl", "curl") .withServer("brave", "brave_local_search", "brave_web_search") .withServer("github-official", Collections.singletonList("add_issue_comment")) .withSecret("brave.api_key", "test_key") .withSecrets(Collections.singletonMap("github.personal_access_token", "test_token")) ) { gateway.start(); assertThat(gateway.getLogs()).contains("4 tools listed"); }

该示例同样来自 DockerMcpGatewayContainerTest.java:通过 try-with-resources 确保测试结束后容器自动停止;注册了curlbravegithub-official三个服务器共 4 个工具(curlbrave_local_searchbrave_web_searchadd_issue_comment),并在启动后断言网关日志输出了4 tools listed,从而验证服务器与工具的注册过程真实生效。

添加模块依赖

Docker MCP Gateway 支持包含在 Testcontainers 核心库中,无需额外添加独立模块依赖。只需将org.testcontainers:testcontainers加入测试依赖即可(将{{latest_version}}替换为实际使用的版本号):

=== "Gradle"groovy testImplementation "org.testcontainers:testcontainers:{{latest_version}}"

=== "Maven"xml <dependency> <groupId>org.testcontainers</groupId> <artifactId>testcontainers</artifactId> <version>{{latest_version}}</version> <scope>test</scope> </dependency>

此外,还需要确保测试环境具备可用的 Docker 运行时(Docker daemon 或兼容的容器运行时),因为 Testcontainers 的一切容器操作都依赖 Docker 客户端。

配置 MCP 服务器与工具

网关本身是一个聚合层:它把多个 MCP 服务器的工具暴露在一个统一的入口后面。DockerMcpGatewayContainer提供两个重载的withServer方法(见 DockerMcpGatewayContainer.java):

public DockerMcpGatewayContainer withServer(String server, List<String> tools) public DockerMcpGatewayContainer withServer(String server, String... tools)
  • 第一个参数server是要注册的 MCP 服务器标识(如curlbravegithub-official);
  • 第二个参数是希望从该服务器暴露给网关的工具名列表(如brave_local_searchadd_issue_comment)。

两个重载方法内部都将服务器名加入servers列表、把工具名加入tools列表,因此可以连续多次调用withServer注册多个服务器。在容器真正启动时(configure()阶段),这些值会被拼装为命令行参数--servers=<server>--tools=<tool>传给网关进程(见 DockerMcpGatewayContainer.java),并配合固定的--transport=sse参数一起以单条 command 方式启动。

注入密钥(Secrets)

许多 MCP 服务器(如 Brave Search、GitHub)需要 API Key 或访问令牌。容器类提供了两种注入方式(见 DockerMcpGatewayContainer.java):

public DockerMcpGatewayContainer withSecrets(Map<String, String> secrets) public DockerMcpGatewayContainer withSecret(String secretKey, String secretValue)
  • withSecret("brave.api_key", "test_key"):逐条注入单个密钥;
  • withSecrets(Collections.singletonMap("github.personal_access_token", "test_token")):一次注入多个密钥。

底层实现上,所有密钥被汇总到内部的secrets映射中;当存在任何密钥时,启动命令会追加--secrets=/testcontainers/app/secrets(见 DockerMcpGatewayContainer.java)。而在容器创建完成后(containerIsCreated回调,见 DockerMcpGatewayContainer.java),容器类会把密钥按key=value格式逐行写入一个文本文件,并通过copyFileToContainer复制到容器内的/testcontainers/app/secrets路径,供网关读取。这种"先启动、后注入文件"的顺序,确保了密钥文件在网关读取配置时已经就位。

获取网关端点

网关容器启动后,测试代码通常需要连接它的 SSE 端点来调用工具。容器类提供getEndpoint()方法(见 DockerMcpGatewayContainer.java):

public String getEndpoint() { return "http://" + getHost() + ":" + getMappedPort(DEFAULT_PORT); }

它基于GenericContainer#getHost()getMappedPort(8811)返回宿主机可访问的地址,格式为http://<host>:<mappedPort>。因为 Testcontainers 会在运行时将容器内端口8811映射到宿主机随机可用端口,测试代码应始终使用getEndpoint()(或getMappedPort(8811))而非硬编码端口,以保证测试在不同机器与 CI 环境下的可移植性。SSE 端点即getEndpoint() + "/sse"(对应容器启动时输出的Start sse server on port日志)。

工作原理与就绪检测

从源码可以梳理出该容器完整的启动链路:

  1. 构造时:解析并校验镜像名与docker/mcp-gateway兼容,暴露端口8811,挂载 Docker 套接字,并注册日志等待策略Wait.forLogMessage(".*Start sse server on port.*", 1)(见 DockerMcpGatewayContainer.java);
  2. configure():把传输模式、服务器列表、工具列表、密钥路径拼成启动命令;
  3. containerIsCreated():容器创建后立即写入密钥文件;
  4. 等待策略:Testcontainers 持续读取容器日志,直到匹配到 SSE 服务启动日志,start()才会返回,保证测试在网关真正可服务之后才继续执行。

因此测试中在start()之后立即getEndpoint()、发起 MCP 调用是安全可靠的。

小结

  • Docker MCP Gateway 支持内置于 Testcontainers 核心库,通过org.testcontainers:testcontainers即可使用;
  • DockerMcpGatewayContainer默认使用docker/mcp-gateway镜像、暴露端口8811、以 SSE 模式启动,并自动挂载 Docker 套接字;
  • 通过withServer(server, tools...)注册 MCP 服务器与工具,通过withSecret/withSecrets注入密钥;
  • 使用getEndpoint()获取可访问的网关地址,结合日志等待策略确保启动完成后才进行业务调用;
  • 相关源码与测试可分别在 DockerMcpGatewayContainer.java 与 DockerMcpGatewayContainerTest.java 中查看,作为自定义扩展与进一步研究的起点。

【免费下载链接】testcontainers-javaTestcontainers is a Java library that supports JUnit tests, providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container.项目地址: https://gitcode.com/GitHub_Trending/te/testcontainers-java

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询