暴露多端口时TestContainers部署RedPanda容器启动失败
RedPanda容器同时暴露8081和9092端口启动失败的修复方案
仅暴露9092端口时RedPanda容器可正常启动,但同时暴露8081(Schema Registry端口)和9092端口后,容器健康检查失败,且9092端口未按预期完成宿主机绑定。
问题根源
问题出在两次调用withCreateContainerCmdModifier并分别创建新的HostConfig。每次调用该方法时,新的HostConfig会完全替换之前的配置,而非合并端口绑定规则。第二次Modifier仅添加了8081的端口绑定,覆盖了第一次添加的9092配置,导致容器启动后9092未绑定到宿主机端口,Testcontainers的健康检查逻辑因找不到预期的端口绑定而超时失败。
修复方案
方案1:在同一个Modifier中合并所有端口绑定
将两个端口的绑定逻辑放在同一个withCreateContainerCmdModifier里,确保HostConfig包含所有需要的端口绑定规则:
private GenericContainer<?> createRpContainer() { try (GenericContainer<?> rpContainer = new GenericContainer<>(DockerImageName.parse("docker.redpanda.com/redpandadata/redpanda:v23.1.10")) .withNetwork(network) .withExposedPorts(8081, 9092) .withCreateContainerCmdModifier(cmd -> { HostConfig hostConfig = new HostConfig(); // 添加8081端口绑定 hostConfig.withPortBindings(new PortBinding(Ports.Binding.bindPort(8081), new ExposedPort(8081))); // 添加9092端口绑定 hostConfig.withPortBindings(new PortBinding(Ports.Binding.bindPort(9092), new ExposedPort(9092))); cmd.withHostConfig(hostConfig); }) ) { return rpContainer; } }
方案2:使用Testcontainers内置的withPortBindings方法(更简洁)
Testcontainers提供了更易用的withPortBindings方法,无需直接操作HostConfig,自动处理端口绑定的合并:
private GenericContainer<?> createRpContainer() { try (GenericContainer<?> rpContainer = new GenericContainer<>(DockerImageName.parse("docker.redpanda.com/redpandadata/redpanda:v23.1.10")) .withNetwork(network) .withExposedPorts(8081, 9092) // 直接添加多个端口绑定 .withPortBindings( new PortBinding(Ports.Binding.bindPort(8081), new ExposedPort(8081)), new PortBinding(Ports.Binding.bindPort(9092), new ExposedPort(9092)) ) ) { return rpContainer; } }
验证
修复后启动容器,执行docker ps查看端口信息,会看到8081和9092都成功绑定到宿主机:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES xxxxxxx docker.redpanda.com/redpandadata/redpanda:v23.1.10 "/entrypoint.sh redp…" xx seconds ago Up xx seconds 0.0.0.0:8081->8081/tcp, 0.0.0.0:9092->9092/tcp, 8082/tcp, 9644/tcp xxxxxxx
内容的提问来源于stack exchange,提问作者curiousengineer
相关产品推荐
相关产品推荐

