Spring Boot容器与Mock Server同网络通信失败问题排查
Spring Boot容器(Testcontainers GenericContainer)无法同网络下的WireMock Mock Server通信
问题描述
我使用Testcontainers的GenericContainer运行Spring Boot镜像data-retriever,期望该容器能消费同网络下WireMock Mock Server返回的模拟数据,编写了如下测试类:
@Slf4j public class TestContainer { private static final Network network = Network.newNetwork(); private static final WireMockContainer wiremockServer = new WireMockContainer("wiremock/wiremock:2.35.0") .withNetwork(network) .withNetworkAliases("mockServer") .withMappingFromResource("weatherMock", "MockData/weatherMock.json") .withMappingFromResource("locationMock", "MockData/locationMock.json"); private static final GenericContainer springBootContainer = new GenericContainer(DockerImageName.parse("data-retriever")) .withNetwork(network); @Autowired @Qualifier("defaultRestTemplate") RestTemplate restTemplate; @Before public void setUpMockServers() { wiremockServer.start(); springBootContainer.dependsOn(wiremockServer) .withImagePullPolicy(PullPolicy.defaultPolicy()) .withExposedPorts(20100) /* update the spring properties using environment variables and make the spring talk to mock server*/ .withEnv("weather_data_host", wiremockServer.getBaseUrl()) .withEnv("location_data_host", wiremockServer.getBaseUrl()) .withStartupTimeout(Duration.of(5, ChronoUnit.MINUTES)); springBootContainer.start(); } @After("@testContainer") public void stopContainer() { wiremockServer.stop(); springBootContainer.stop(); } @Given("I am mock dependency using wiremock testcontainers") public void iAmMockDependencyUsingWiremockTestcontainers() { log.info("dataIngestion server host: {}", springBootContainer.getHost()); log.info("dataIngestion server port: {}", springBootContainer.getFirstMappedPort()); String url = String.format("https://%s:%s/retrieveData", springBootContainer.getHost(), springBootContainer.getFirstMappedPort()); var response = restTemplate.getForEntity(url, Object.class); Assert.assertTrue(response.getStatusCode().is2xxSuccessful()); } }
运行测试时,data-retriever容器无法与Mock Server容器通信,但通过Postman能正常访问Mock Server获取模拟数据。我使用wiremockServer.getBaseUrl()获取Mock Server的主机和端口并传入Spring容器的环境变量。
疑问
- 为何同网络下data-retriever容器无法与Mock Server容器通信?
- 是否需要进行额外配置?
解决方案
问题原因
核心问题是误用了wiremockServer.getBaseUrl():这个方法返回的是宿主机(本地机器)的IP加上WireMock容器映射到宿主机的端口,而Docker容器之间在同一自定义网络内通信时,必须使用容器的网络别名+容器内部的端口,而非宿主机的映射地址。
WireMock容器默认内部端口为8080(你使用的2.35.0版本遵循此默认值),且你已经给WireMock容器设置了网络别名mockServer,所以Spring Boot容器内部必须用http://mockServer:8080作为Mock Server的访问地址。
具体修改
修改Spring Boot容器的环境变量配置,替换错误的地址:
// 原代码 .withEnv("weather_data_host", wiremockServer.getBaseUrl()) .withEnv("location_data_host", wiremockServer.getBaseUrl()) // 修改后 .withEnv("weather_data_host", "http://mockServer:8080") .withEnv("location_data_host", "http://mockServer:8080")
额外检查点
- 确认Spring Boot应用中是否正确读取这两个环境变量,确保请求Mock Server的URL是基于
http://mockServer:8080构建的,而非硬编码的其他地址。 - 若自定义过WireMock的内部端口,需将上述地址中的
8080替换为自定义端口。 - 查看Spring Boot容器的日志,若仍有问题,可通过日志中的连接超时、DNS解析失败等信息进一步定位问题。
关于额外配置的疑问
不需要额外的网络配置:你已经创建了自定义网络并让两个容器加入该网络,同时设置了WireMock的网络别名,只要地址使用正确,容器之间就能正常通信。
内容的提问来源于stack exchange,提问作者Golden Heart
相关产品推荐
相关产品推荐

