BoJack Horseman
BoJack Horseman

Reputation: 4452

Access IP of docker container at runtime

I have cross browser tests that I have written with selenium. Since I want to test multiple browsers on multiple platforms I use docker virtualization and selenium grid. I could execute my tests without docker via localhost:4444 with this docker-compose.yml

version: "3"
services:
  hub:
    image: selenium/hub
    ports:
      - "4444:4444"
    environment:
      GRID_MAX_SESSION: 16
      GRID_BROWSER_TIMEOUT: 3000
      GRID_TIMEOUT: 3000

  chrome:
    image: selenium/node-chrome
    container_name: web-automation_chrome
    depends_on:
      - hub
    environment:
      HUB_PORT_4444_TCP_ADDR: hub
      HUB_PORT_4444_TCP_PORT: 4444
      NODE_MAX_SESSION: 4
      NODE_MAX_INSTANCES: 4
    volumes:
      - /dev/shm:/dev/shm
    ports:
      - "9001:5900"

  firefox:
    image: selenium/node-firefox
    container_name: web-automation_firefox
    depends_on:
      - hub
    environment:
      HUB_PORT_4444_TCP_ADDR: hub
      HUB_PORT_4444_TCP_PORT: 4444
      NODE_MAX_SESSION: 2
      NODE_MAX_INSTANCES: 2
    volumes:
      - /dev/shm:/dev/shm
    ports:
      - "9002:5900"

  opera:
    image: selenium/node-opera
    container_name: web-automation_opera
    depends_on:
      - hub
    environment:
      HUB_PORT_4444_TCP_ADDR: hub
      HUB_PORT_4444_TCP_PORT: 4444
      NODE_MAX_SESSION: 2
      NODE_MAX_INSTANCES: 2
    volumes:
      - /dev/shm:/dev/shm
    ports:
      - "9003:5900"

I just executed my tests with maven and they would succeed. Then I planned to containerize also my browser JUnit tests and created this Dockerfile:

FROM openjdk:11 as build
WORKDIR /workspace/app

COPY .git .git
COPY mvnw .
COPY .mvn .mvn
COPY wait-for-it.sh .
RUN ["chmod", "+x", "wait-for-it.sh"]
COPY pom.xml .
COPY src src

RUN ./wait-for-it.sh hub:4444 -- ./mvnw clean package

FROM openjdk:11
VOLUME /tmp
COPY --from=build /workspace/app/target/*.jar app.jar

Which should work fine as well and added this part to my docker-compose.yml:

  app:
    build: .
    ports:
      - "80:8080"
    depends_on:
      - "hub"

As soon as I run docker-compose up, the maven builds the tests successfully and selenium grid is set up successfully but I receive the following error:

[ERROR] loginUserNotExistentFirefox  Time elapsed: 0.033 s  <<< ERROR!
org.openqa.selenium.remote.UnreachableBrowserException: 
Could not start a new session. Possible causes are invalid address of the remote server or browser start-up failure.
Build info: version: '3.141.59', revision: 'e82be7d358', time: '2018-11-14T08:17:03'
System info: host: '7e67c412b3c0', ip: '172.17.0.2', os.name: 'Linux', os.arch: 'amd64', os.version: '4.19.121-linuxkit', java.version: '11.0.9.1'
Driver info: driver.version: RemoteWebDriver
        at org.seleniumtests.frontendtests.tests.TestLogin.loginUserNotExistentFirefox(TestLogin.java:29)
Caused by: java.net.UnknownHostException: hub
        at org.seleniumtests.frontendtests.tests.TestLogin.loginUserNotExistentFirefox(TestLogin.java:29)

This is how I plan to reach the service from my app container.

    driver = new RemoteWebDriver(new URL("http://hub:4444/wd/hub"),
                                                             DesiredCapabilities.operaBlink());

Upvotes: 0

Views: 1848

Answers (1)

Marte Valerio Falcone
Marte Valerio Falcone

Reputation: 455

First problem: you can't connect to localhost:4444

There's a bridge (by default in Docker Compose) between your services, and you can access to another service by <service_name>:<service_port>, so you can access hub service by hub:4444.

Second problem, it may be outcome when you solve the first problem

From the official Docker Compose documentation, as you can read here:

You can control the order of service startup and shutdown with the depends_on option. Compose always starts and stops containers in dependency order, where dependencies are determined by depends_on, links, volumes_from, and network_mode: "service:...".

As you did with depends_on, but

However, for startup Compose does not wait until a container is “ready” (whatever that means for your particular application) - only until it’s running. There’s a good reason for this.

Docker Compose official solution

Use a tool such as wait-for-it, dockerize, sh-compatible wait-for, or RelayAndContainers template. These are small wrapper scripts which you can include in your application’s image to poll a given host and port until it’s accepting TCP connections.

They suggest you to act like this:

version: "3"
services:
  hub:
    image: selenium/hub
    ports:
      - "4444:4444"
    environment:
      GRID_MAX_SESSION: 16
      GRID_BROWSER_TIMEOUT: 3000
      GRID_TIMEOUT: 3000

  app:
    build: .
    ports:
      - "80:8080"
    depends_on:
      - "hub"
    command: ["./wait-for-it.sh", "hub:4444", "--", "java", "-jar", "app.jar"]

Upvotes: 1

Related Questions