6

I would like to run a container with testcontainers on a network. My containers contains a spring application, which has an actuator endpoint to express its state, it is on:

/actuator/health

My container looks like the following:

private final static Network network = Network.newNetwork();

private static final GenericContainer<?> myContainer = new GenericContainer<>("mycontainer:latest")
            .withExposedPorts(8443)
            .withNetwork(network)
            .withNetworkAliases("myContainer")
            .withClasspathResourceMapping("certs", "/app/certs", BindMode.READ_ONLY)
            .withClasspathResourceMapping("config", "/app/config", BindMode.READ_ONLY)
            .withLogConsumer(new Slf4jLogConsumer(log))
            .waitingFor(Wait.forHttp("/actuator/health").usingTls());

But when i start this container I get the following error:

Caused by: org.testcontainers.containers.ContainerLaunchException: Timed out waiting for URL to be accessible (https://localhost:33092/actuator/health should return HTTP [200])
    at org.testcontainers.containers.wait.strategy.HttpWaitStrategy.waitUntilReady(HttpWaitStrategy.java:214)
    at org.testcontainers.containers.wait.strategy.AbstractWaitStrategy.waitUntilReady(AbstractWaitStrategy.java:35)
    at org.testcontainers.containers.GenericContainer.waitUntilContainerStarted(GenericContainer.java:890)
    at org.testcontainers.containers.GenericContainer.tryStart(GenericContainer.java:441)
    ... 68 more

But if I curl this url (in this example: https://localhost:33092/actuator/health) while after the application inside the container has started but I am waiting for the evaulation, I get something like this:

HTTP Status Code: 200
{
    "status": "UP"
}

What am I missing? Any ideas? Is it a bug?

Five
  • 378
  • 2
  • 19
  • .withExposedPorts(8443) should it be 33092 ? – Fabien MIFSUD Dec 04 '20 at 12:01
  • Does it work without TLS? Without custom network? – Vitaly Chura Dec 04 '20 at 12:23
  • @FabienMIFSUD No, the parameter passed to .withExposedPorts(), is the port INSIDE the container. On the host Testcontainers maps it to the random port, which in this case as I understand happens to be 33092. If you get interested - https://www.testcontainers.org/features/networking/#exposing-container-ports-to-the-host – Vitaly Chura Dec 04 '20 at 12:28
  • @VitalyChura no, sadly it does not work without TLS. Custom network is required since it is dependent on other containers. The exposed ports will be mapped to localhost:33092. The port number is an random unused port so cant expose it. I still don't understand that how can i call it from outside and works perfectly but this waitstrategy it dont. – Five Dec 04 '20 at 13:51

1 Answers1

0

Ok, so you'll have to decompose the problem.

I just built an example Spring Boot app with dependencies and packed it in an image:

implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-web'

Nothing else, I downloaded it from https://start.spring.io/

The following test class works (I took your code as an example):

import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.output.Slf4jLogConsumer;
import org.testcontainers.containers.wait.strategy.Wait;

@Slf4j
public class TestcontainersWithSpringActuator {

    private static final GenericContainer<?> myContainer = new GenericContainer<>("docker.io/vcvitaly/test_sb:latest")
            .withExposedPorts(8080)
            .withNetworkAliases("myContainer")
            .withLogConsumer(new Slf4jLogConsumer(log))
            .waitingFor(Wait.forHttp("/actuator/health"));

    @Test
    void name() {
        myContainer.start();
        System.out.println();
    }
}

I can also put a break on System.out.println and while it's suspended curl also works

~  curl http://localhost:32776/actuator/health
{"status":"UP"}⏎

I don't really have a straight guess right now what is happening in your case, but you have to decompose you problem layer by layer (getting rid of tls, network, etc) or build it up starting from scratch with the most simple image and adding features one by one.

Vitaly Chura
  • 704
  • 8
  • 13