Spring Boot 3.1使用Testcontainers指定Postgres版本遇问题求助
问题场景
Spring Boot 3.1新增了开发环境下管理Testcontainers的支持,尝试在项目中使用指定版本的Postgres镜像时遇到连续错误:
首次尝试代码
public class TestDemoApplication { public static void main(String[] args) { SpringApplication.from(DemoApplication::main) .with(MyContainersConfiguration.class) .run(args); } @TestConfiguration public static class MyContainersConfiguration { @Bean @ServiceConnection public PostgreSQLContainer<?> postgresContainer() { return new PostgreSQLContainer<>("postgresql:15-alpine3.17"); } } }
首次错误
Caused by: java.lang.IllegalStateException: Failed to verify that image 'postgresql:15-alpine3.17' is a compatible substitute for 'postgres'. This generally means that you are trying to use an image that Testcontainers has not been designed to use. If this is deliberate, and if you are confident that the image is compatible, you should declare compatibility in code using the
asCompatibleSubstituteFormethod. For example:
DockerImageName myImage = DockerImageName.parse("postgresql:15-alpine3.17").asCompatibleSubstituteFor("postgres");
and then usemyImageinstead.
按提示修改后的代码
@Bean @ServiceConnection public PostgreSQLContainer<?> postgresContainer() { return new PostgreSQLContainer<>( DockerImageName.parse("postgresql:15-alpine3.17") .asCompatibleSubstituteFor("postgres")); }
二次错误
Caused by: com.github.dockerjava.api.exception.NotFoundException: Status 404: {"message":"pull access denied for postgresql, repository does not exist or may require 'docker login': denied: requested access to the resource is denied"}
at org.testcontainers.shaded.com.github.dockerjava.core.DefaultInvocationBuilder.execute(DefaultInvocationBuilder.java:241) ~[testcontainers-1.18.0.jar:1.18.0] at org.testcontainers.shaded.com.github.dockerjava.core.DefaultInvocationBuilder.lambda$executeAndStream$1(DefaultInvocationBuilder.java:269) ~[testcontainers-1.18.0.jar:1.18.0] at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]
解决办法
核心问题是镜像名称错误:Docker Hub官方Postgres镜像的仓库名是postgres,而非postgresql,之前的镜像名写错导致Docker找不到对应仓库,触发404错误。
修正方案1:直接使用正确官方镜像名(无需额外兼容性声明)
@Bean @ServiceConnection public PostgreSQLContainer<?> postgresContainer() { return new PostgreSQLContainer<>("postgres:15-alpine3.17"); }
修正方案2:保留兼容性声明的正确写法
@Bean @ServiceConnection public PostgreSQLContainer<?> postgresContainer() { return new PostgreSQLContainer<>( DockerImageName.parse("postgres:15-alpine3.17") .asCompatibleSubstituteFor("postgres")); }
说明
- 官方Postgres镜像的Docker Hub仓库为
postgres,修正镜像名后,Testcontainers的兼容性校验会自动通过,无需额外声明(声明也不会产生负面影响)。
内容的提问来源于stack exchange,提问作者Kevin

