I am running selenium test in Gitlab CI, but have problem with setting remote URL correctly when using the gitlab runner instead of my computer.
The IP address of the runner is 192.168.xxx.xxx
. And when I run the pipeline, I got the IP address of selenium hub is 172.19.0.2/16
. I tried both, and both failed. I also tried to use the name of the selenium hub container http://selenium__hub
, but it also failed.
The docker-compose.yml is:
version: "3"
services:
chrome:
image: selenium/node-chrome:4.0.0-20211013
container_name: chrome
shm_size: 2gb
depends_on:
- selenium-hub
volumes:
- ./target:/home/seluser/Downloads
environment:
- SE_EVENT_BUS_HOST=selenium-hub
- SE_EVENT_BUS_PUBLISH_PORT=4442
- SE_EVENT_BUS_SUBSCRIBE_PORT=4443
- SE_NODE_GRID_URL=http://localhost:4444
ports:
- "6900:5900"
edge:
image: selenium/node-edge:4.0.0-20211013
container_name: edge
shm_size: 2gb
depends_on:
- selenium-hub
volumes:
- ./target:/home/seluser/Downloads
environment:
- SE_EVENT_BUS_HOST=selenium-hub
- SE_EVENT_BUS_PUBLISH_PORT=4442
- SE_EVENT_BUS_SUBSCRIBE_PORT=4443
- SE_NODE_GRID_URL=http://localhost:4444
ports:
- "6901:5900"
firefox:
image: selenium/node-firefox:4.0.0-20211013
container_name: firefox
shm_size: 2gb
depends_on:
- selenium-hub
volumes:
- ./target:/home/seluser/Downloads
environment:
- SE_EVENT_BUS_HOST=selenium-hub
- SE_EVENT_BUS_PUBLISH_PORT=4442
- SE_EVENT_BUS_SUBSCRIBE_PORT=4443
- SE_NODE_GRID_URL=http://localhost:4444
ports:
- "6902:5900"
selenium-hub:
image: selenium/hub:4.0.0-20211013
container_name: selenium-hub
ports:
- "4444:4444"
the gitlab runner's config file looks like this:
[[runners]]
name = "selenium"
url = "https://gitlab.myhost.at"
token = "xxxxxxxx"
executor = "docker"
privileged = true
links = ["selenium__hub:hub"]
[runners.docker]
image = "docker:stable"
privileged = true
The remote url I have tried are:
WebDriver driver = new RemoteWebDriver(new URL("http://192.168.xxx.xxx:4444/wd/hub"), cap);
WebDriver driver = new RemoteWebDriver(new URL("http://172.19.0.2:4444/wd/hub"), cap);
WebDriver driver = new RemoteWebDriver(new URL("http://selenium__hub:4444/wd/hub"), cap);
How can I get this to work with GitLab runner?
CodePudding user response:
The issue here is when your job launches containers using docker-compose
, the hostnames in the docker network are not known to your job container.
Assuming you are using the docker:dind
service in your job to use docker-compose
and you are trying to connect to your services started with docker-cmpose
from your job, you would need to use the hostname docker
to reach your services through their mapped ports.
So your corrected code would be as follows:
WebDriver driver = new RemoteWebDriver(new URL("http://docker:4444/wd/hub"), cap);
Why "docker"?
The reason this is needed is because your containers are running 'on' a remote docker daemon service -- the docker:dind
container. When you invoke docker-compose
your job container talks to the docker:dind
container which in turn spins up a new docker network and creates the docker containers in your compose file on that network.
Your job container has no knowledge of (or route to) that network, nor does it know the hostnames of the services. The service daemon itself also is running on a separate network from your runner -- because it is another docker container that was created by the docker executor; so your runner IP won't work either.
However, the docker executor does create a link to your services:
I.E. the docker:dind
service. So you can reach that container by the docker
hostname. Additionally, your compose file indicates that the hub service should make a port mapping of 4444:4444
from the host -> continaer. The host, in this case, means the docker:dind
service. So calling http://docker:4444
from your job reaches the hub service.
Why doesn't "links" work?
Finally, to cover one last detail, it looks like in your runner configuration you expected your links
to allow you to communicate with the hub container by hostname:
links = ["selenium__hub:hub"]
In the runner configuration, it's true that the links
configuration, in general, would allow your job to communicate with containers by hostname. However, this configuration is errant for two reasons:
- This configuration can only apply to containers alongside your runner container. That is other containers registered on the host daemon -- not containers created by other docker daemons, like the ones created with
docker-compose
in your job by talking to thedocker:dind
service daemon. - Even if you could reach containers created by other daemons, or your hub container was created by the host daemon, the parameters are wrong, according to the URLS you tried. This configuration basically says "expose the
selenium__hub
container as the FQDNhub
" -- but you never tried the hostnamehub
.
There is nothing to fix here because (1) is not a fixable error when using docker-in-docker.
Alternatives
Alternatively, you can utilize GitLab's services:
capability to run the hub and/or browser containers.
my_job:
services:
- docker:dind
- name: selenium/hub:4.0.0-20211013
alias: hub # this is the hostname
You could even do this as a runner configuration and give it a special tag and jobs needing remote browsers can just add the necessary tags:
key(s) to reduce the amount of job configuration needed.
You may also be interested to see one of my other answers on how FF_NETWORK_PER_BUILD
feature flag can affect how networking works between docker containers and jobs/services.