Run ES docker image with custom port using testcontainers
Asked Answered
S

4

5

I want to run a container tests that running ES image via Docker. After some research I found https://www.testcontainers.org/ and they also have a built-it ES module.

Because my development environment using ES in ports 9200 and 9300 I prefer to use another ports for my tests, let’s say 1200 and 1300. Therefore, to run the docker image from CLI I use this command:

docker run -p 1200:9200 -p 1300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:7.6.2

I tried to do it with testcontainers, for example:

static ElasticsearchContainer esContainer =
        new ElasticsearchContainer("docker.elastic.co/elasticsearch/elasticsearch:7.6.2")
                .withExposedPorts(1200, 9200)
                .withExposedPorts(1300, 9300)
                .withEnv("discovery.type", "single-node");
                // .waitingFor(Wait.forHttp("/")); // Wait until elastic start – cause an error

@BeforeClass
public static void initEsDockerImage() {
    esContainer.start();
    esContainer.isRunning();
}

breakpoint in esContainer.isRunning():

port is 32384, run esContainer.getHttpHostAddress() return localhost/127.0.0.1:32847 and also from docker dashboard: Anyway, failed to make ES connection with both (1200 and 32384).

run the start() line with the **waitingFor** command throws Container startup failed error

Another question, how can I know the schema (http or https) in testcontainers?

Sipper answered 20/5, 2020 at 13:1 Comment(0)
E
6

If you want to specify a port instead of using a random one, you can do it with this:

static final MySQLContainer<?> mysql =
    new MySQLContainer<>("mysql:5.6")
        .withExposedPorts(34343)
        .withCreateContainerCmdModifier(cmd -> cmd.withHostConfig(
            new HostConfig().withPortBindings(new PortBinding(Ports.Binding.bindPort(34343), new ExposedPort(3306)))
        ));
Earshot answered 1/4, 2021 at 11:9 Comment(0)
S
3

I'm doing it wrong. withExposedPorts allows us to expose ports from the container’s perspective (which I don’t need to do in this case since ElasticContainer already exposes an http port (9200) and a tcp port (9300)).

To find out the random port on the host (on which the test runs) that these ports were mapped, call getMappedPort(9200) or in the case of ElasticContainer to get the host:port you call getHttpHostAddress().

More info here: https://www.testcontainers.org/features/networking/

Bottom line, change the init to:

static ElasticsearchContainer esContainer =
    new ElasticsearchContainer("docker.elastic.co/elasticsearch/elasticsearch:7.6.2")
            .withEnv("discovery.type", "single-node");

Get the port by:

int containerPort = esContainer.getMappedPort(9200);

P.S. About the schema - I still don't know but looks like testContainer runs on https..

Sipper answered 21/5, 2020 at 6:36 Comment(0)
C
1

I was able to get it working as below. I have to set 9200 for withExposedPorts()

container = new ElasticsearchContainer(ELASTICSEARCH_IMAGE)
            .withEnv("discovery.type", "single-node")
            .withExposedPorts(9200)     
            .withCreateContainerCmdModifier(cmd -> cmd.withHostConfig(
                        new HostConfig().withPortBindings(new PortBinding(Ports.Binding.bindPort(34343), new ExposedPort(9200)))));

Here is the log:

 org.elasticsearch.client.RestClient - request [GET http://localhost:34343/] returned 1 warnings
Cardinale answered 21/4, 2022 at 22:21 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Andres
N
0

You just need to bind a specific ports, this is since the generic container implementation binds a free random one by default

    List<String> portBindings = container.getPortBindings();
    portBindings.add(String.format("%d:%d/%s", ES_PORT_HOST, ES_PORT_CONTAINER, InternetProtocol.TCP));
    container.setPortBindings(portBindings);

     // or just in one line if no previous binding required
     // container.setPortBindings(List.of(String.format("%d:%d/%s", ES_PORT_HOST, ES_PORT_CONTAINER, InternetProtocol.TCP)));
Naman answered 16/7, 2021 at 17:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.