How to access dockerized app under test in gitlab CI

Viewed 340

I have testng project with selenium for integration testing of frontend app in vuejs and springboot backend. So in order to run tests I need first to bring up all dependent projects:

  • springboot and mongodb
  • vuejs frrontend app

Each project is in its own repo. So I have created docker images of springboot and frontend app and will put it up in gitlab container registry. Then in the testeng project plan to use docker-compose in .gitlab-ci.yml. Here is docker-compose.yml for testng project:

version: '3.7'
services:
  frontendapp:
    image: demo.app-frontend-selenium
    container_name: frontend-app-selenium
    depends_on:
      - demoapi
    ports:
      - 8080:80
  demoapi:
    image: demo.app-backend-selenium
    container_name: demo-api-selenium
    depends_on:
      - mongodb
    environment:
      - SPRING_PROFILES_ACTIVE=prod
      - SCOUNT_API_ENDPOINTS_WEB_CORS_OPTIONS_ALLOWEDORIGINS=*
      - SPRING_DATA_MONGODB_HOST=mongodb
      - SPRING_DATA_MONGODB_DATABASE=demo-api-selenium
      - KEYCLOAK_AUTH-SERVER-URL=https://my-keycloak-url/auth
    ports:
      - 8082:80
  mongodb:
    image: mongo:4-bionic
    container_name: mongodb-selenium
    environment:
      MONGO_INITDB_DATABASE: demo-api-selenium
    ports:
      - 27017:27017
    volumes:
      - ./mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro

After running docker-compose in gitlab-ci.yml what will be url of frontend app in order to execute tests? When I do it locally I am using following urls for testing:

  • frontend app: http://localhost:8080
  • api: http://localhost:8082

But in case when running on gitlab ci what will be url to access frontend and api?

1 Answers

TL;DR instead of using localhost you need to use the hostname of your docker daemon (docker:dind) service. If you setup docker-in-docker for your GitLab job per usual setup, this is most likely docker.

So the urls you need to use according to your compose file are:

  • frontend app: http://docker:8080
  • api: http://docker:8082
my_job:
  services:
    - name: docker:dind
      alias: docker  # this is the hostname of the daemon

  variables:
    DOCKER_TLS_CERTDIR: ""
    DOCKER_HOST: "tcp://docker:2375"
  image: docker:stable
  script:
    - docker run -d -p 8000:80 strm/helloworld-http
    - apk update && apk add curl # install curl and let server start
    - curl http://docker:8000 # use the daemon to reach your containers

For a full explanation of this, read on.

Docker port mapping in Gitlab CI vs locally

How it works locally

Normally, when you use docker-compose locally on your system, you are typically running the docker daemon on your localhost (e.g. using docker desktop).

When you provide a port mapping like 8080:80 it means to publish port 8080 on the daemon host bound to port 80 in the container. When running locally, that means you can reach the container via localhost.

In GitLab

However, when you're running docker-in-docker on GitLab CI the important difference in this environment is that the docker daemon is remote. So, when you expose ports through the docker API, the ports are exposed on the docker daemon host not locally in your job container.

Hence, you must use the hostname of the docker daemon, not localhost, to reach your started containers.

Alternative solutions

An alternative to this would be to conduct your testing inside the same docker network that you create with your compose stack. That way, your testing is agnostic of where the docker environment lives and can, for example, leverage the service aliases in your compose file (like frontendapp, demoapi, etc) instead of relying on published ports.

For example, you may choose add a test container to your compose stack. Some testing libraries like Testcontainers can help set this up, too.

Related