Search code examples
javadockerjunitdockerfiletestcontainers

testcontainers - cannot connect to exposed port of generic container


I am trying to launch a custom docker container using GenericContainer. Once the container is launched, I would like to execute a http request from a test class. I am seeing this error :

INFO: Exposed ports: 9000

java.net.ConnectException: Failed to connect to localhost/0:0:0:0:0:0:0:1:9000
    at org.testcontainers.shaded.okhttp3.internal.connection.RealConnection.connectSocket(RealConnection.java:265)

Caused by: java.net.ConnectException: Connection refused (Connection refused)
    at java.base/java.net.PlainSocketImpl.socketConnect(Native Method)

the port appears to be bound:

docker ps -a
CONTAINER ID   IMAGE                                            COMMAND                  CREATED              STATUS              PORTS                                                                                      NAMES
f311467dbd25   foo.bar.com/abc-def/testcontainer:4.30.65   "/bin/sh -c 'exec /o…"   About a minute ago   Up About a minute   0.0.0.0:55164->9000/tcp, :::55164->9000/tcp, 0.0.0.0:55163->9001/tcp, :::55163->9001/tcp   happy_jepsen

I am creating the container with this code:

        myContainerInstance = new GenericContainer<>(MY_CONTAINER_IMAGE)
                .withNetworkAliases("foo")
                .withCreateContainerCmdModifier(createContainerCmd -> createContainerCmd.withHostName("foo"))
                .waitingFor(new WaitAllStrategy().withStrategy(new LogMessageWaitStrategy().withRegEx(".*Listening for HTTP on.*"))
                        .withStartupTimeout(Duration.ofMinutes(4)))
                .withExposedPorts(9000)

The client code:

    OkHttpClient client = new OkHttpClient();
        String url = "http://localhost:9000/testget";
        String output = run(url);
        logger.info("Response is: " + output);

    }
    String run(String url) throws IOException {
        Request request = new Request.Builder()
                .url(url)
                .addHeader("Content-type", "application/json")
                .build();

        try (Response response = client.newCall(request).execute()) {
            return response.body().string();
        }
    }

Additional details:

  1. lsof -i :9000 does not show any bound port on my local machine
  2. Wait strategy of waitForHttpPort does not work (container start times out)

I would appreciate any help in figuring out why.


Solution

  • If you say testcontainers to expose port 9000, that means, to bind the port 9000 inside the container to some free port on the local machine, it does not mean, that the local port 9000 is bound to something.

    You can ask the container to which local port the exposed container port is bound (e.g. containerinstance.getMappedPort(9000)

    If your client is not in a container, it has to connect to the local port. If it is inside the container (or any container in the same docker network) use port 9000.