如何解决 Spring Boot 上的 org.testcontainers.containers.ContainerFetchException?

Posted

技术标签:

【中文标题】如何解决 Spring Boot 上的 org.testcontainers.containers.ContainerFetchException?【英文标题】:How to resolve org.testcontainers.containers.ContainerFetchException on Spring Boot? 【发布时间】:2020-12-16 06:23:47 【问题描述】:

我正在为我的 Spring Boot 应用程序开发一些集成测试。我正在使用testcontainers 来创建MongoDB docker 映像。到目前为止我的代码:

ContainerListener.java 类:

公共类 ContainerListener 实现 TestListener

@ClassRule
public static Network sharedNetwork = Network.newNetwork();

@ClassRule
public static GenericContainer mongoDBContainer = new GenericContainer("mongo:3.2.4").withNetwork(sharedNetwork)
        .withNetworkAliases("mongo").withExposedPorts(27017);

public static MockServerContainer mockServerContainer = new MockServerContainer().withNetwork(sharedNetwork)
        .withNetworkAliases("mockserver").withExposedPorts(1080);

public static int getMockPort() 
    return mockServerContainer.getMappedPort(1080);


public static int getMongoPort() 
    return mongoDBContainer.getMappedPort(27017);


public static void runAll() 
    List.of(mongoDBContainer, mockServerContainer).forEach(e -> e.start());


public static void stopAll() 
    List.of(mongoDBContainer, mockServerContainer).forEach(e -> e.stop());

还有SomeControllerIntegrationTest.java类:

import io.restassured.RestAssured;
import io.restassured.parsing.Parser;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

import static io.restassured.RestAssured.given;

public class RatingControllerIntegrationTest 

    @BeforeAll
    public static void setuo() 
        ContainerListener.runAll();

    

    @AfterAll
    public static void tearDown() 
        ContainerListener.stopAll();
    

    @Test
    public void detailsTest() throws Exception 
        RestAssured.enableLoggingOfRequestAndResponseIfValidationFails();
        RestAssured.defaultParser = Parser.JSON;

        given().log().all().when().get("http://localhost:8080/actuator/info/").then().log().all()
                .statusCode(200);
    


尽管运行测试后我收到以下错误:

org.testcontainers.containers.ContainerLaunchException: Container startup failed

Caused by: org.testcontainers.containers.ContainerFetchException: Can't get Docker image: RemoteDockerImage(imageName=mongo:3.2.4, imagePullPolicy=DefaultPullPolicy())
    at org.testcontainers.containers.GenericContainer.getDockerImageName(GenericContainer.java:1279)
    at org.testcontainers.containers.GenericContainer.logger(GenericContainer.java:613)
    at org.testcontainers.containers.GenericContainer.doStart(GenericContainer.java:320)
    ... 58 more
Caused by: java.lang.IllegalStateException: Can not connect to Ryuk at localhost:32770
    at org.testcontainers.utility.ResourceReaper.start(ResourceReaper.java:176)
    at org.testcontainers.DockerClientFactory.client(DockerClientFactory.java:168)
    at org.testcontainers.LazyDockerClient.getDockerClient(LazyDockerClient.java:14)
    at org.testcontainers.LazyDockerClient.listImagesCmd(LazyDockerClient.java:12)
    at org.testcontainers.images.LocalImagesCache.maybeInitCache(LocalImagesCache.java:68)
    at org.testcontainers.images.LocalImagesCache.get(LocalImagesCache.java:32)
    at org.testcontainers.images.AbstractImagePullPolicy.shouldPull(AbstractImagePullPolicy.java:18)
    at org.testcontainers.images.RemoteDockerImage.resolve(RemoteDockerImage.java:59)
    at org.testcontainers.images.RemoteDockerImage.resolve(RemoteDockerImage.java:26)
    at org.testcontainers.utility.LazyFuture.getResolvedValue(LazyFuture.java:20)
    at org.testcontainers.utility.LazyFuture.get(LazyFuture.java:27)
    at org.testcontainers.containers.GenericContainer.getDockerImageName(GenericContainer.java:1277)
    ... 60 more

【问题讨论】:

【参考方案1】:

如果你还没有看到:https://github.com/testcontainers/testcontainers-java/issues/3166

github 用户@bsideup 概述了三个选项。当然,这仅适用于使用 Docker for Mac 的 Mac 用户。

使用包含修复的 Testcontainers 1.15.0-rc2 在 Docker for Mac 2.4.0 中禁用 gRPC FUSE 降级到 Docker for Mac 2.3.x

这(禁用 gRPC)为我解决了这个问题,所以我将其作为参考。根据您的工作流程,不使用 gRPC FUSE 可能会产生重大影响。所以你最好检查一下这是否很好或更好地降级到 Docker for Mac 2.3.x。我没有选择第一个选项,因为它似乎不会停止容器,这对我来说是所有选项中最糟糕的。

【讨论】:

【参考方案2】:

使用 Ubuntu 操作系统和构建 java 项目时出现此异常。集成测试立即开始失败。尝试了不同的选项,但无法解决问题。

在 Ubuntu 操作系统中,为了访问 docker 命令,我们使用 root 权限(即我们使用 sudo 命令和 docker 命令)。为了构建 java 项目,我使用了 sudo 命令。请参考以下命令。

sudo ./gradlew clean build

上面的命令解决了这个问题。

【讨论】:

以上是关于如何解决 Spring Boot 上的 org.testcontainers.containers.ContainerFetchException?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 spring-boot 中拦截嵌入式 Tomcat 上的“全局”404

Spring boot + spring security - 如何阻止应用层上的CORS请求?

如何运行部署在 AWS 上的 Spring Boot 程序 [关闭]

如何将我的 Spring Boot 应用程序连接到 Docker 上的 Redis 容器?

如何解决 CockroachDB 和 Spring-Boot 的密码问题

java - 如何在Java Spring Boot上的firebase存储中获取上传文件的downloadURL