如何解决在Spring Boot中出现的org.testcontainers.containers.ContainerFetchException错误?

huangapple go评论80阅读模式
英文:

How to resolve org.testcontainers.containers.ContainerFetchException on Spring Boot?

问题

ContainerListener.java 类:

public class ContainerListener implements 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 setup() {
        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
英文:

I am working on developing a few integration tests for my spring boot application. I am using testcontainers in order to create a MongoDB docker image. My code so far:

ContainerListener.java class:

public class ContainerListener implements 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());
}

}

And SomeControllerIntegrationTest.java class:

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);
	}

}

Despite that after running the tests I get the following error:

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

得分: 4

如果你还没有看过: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。我没有选择第一个选项,因为似乎它不会停止容器,这对我来说是所有选项中最糟糕的。

英文:

If you haven't seen yet: https://github.com/testcontainers/testcontainers-java/issues/3166

github user @bsideup outlined three options. This will of course only apply to you if you are a Mac User using Docker for Mac.

  • use Testcontainers 1.15.0-rc2 that includes the fix
  • Disable gRPC FUSE in Docker for Mac 2.4.0
  • Downgrade to Docker for Mac 2.3.x

This (disable gRPC) solved the issue for me so I leave this as a reference. Not using gRPC FUSE can have significant impact depending on your workflow. So you better check if that is fine or better downgrade to Docker for Mac 2.3.x. I did not pick the first option as it seems it does not stop containers which is the worst of all the options for me.

答案2

得分: 0

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

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

sudo ./gradlew clean build

上述命令解决了这个问题。

英文:

This exception came when using Ubuntu operating system and when building the java project. The integration test started to fail at once. Tried with different option but could not resolve the issue.

In Ubuntu OS, in order to access the docker command we use root permission(i.e We use sudo command with docker command). In order to build the java project I have used the sudo command. Please refer the below command.

> sudo ./gradlew clean build

The above command fixed the issue.

huangapple
  • 本文由 发表于 2020年8月27日 19:13:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/63614788.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定