SLOBY
SLOBY

Reputation: 1107

How are Gitlab CI service ports exposed?

I have a .gitlab-ci.yml file:

integration_test:
  services:
    - name: registry.gitlab.com/group/project/testmailserver:1.1
      alias: "mail.email"
  stage: test
  script:
    - ./gradlew -g /cache/.gradle --stacktrace --info integrationTest

The service is a full stack email server based on this: tvial/docker-mailserver:latest. Locally with my docker-compose config I'm able to run it and connect to it.

version: '2'

services:
  mail:
    image: registry.gitlab.com/group/project/testmailserver:1.1
    hostname: mail
    domainname: localhost
    ports:
      - "25:25"
      - "143:143"
      - "587:587"
      - "993:993"
    environment:
      - ONE_DIR=1
      - DMS_DEBUG=0
      - MAIL_USER=invoicereader
      - MAIL_PASS=invoicereader
    cap_add:
      - NET_ADMIN

If I run it with docker-compose up and connect to it via IMAP on port 993 it works fine. Also the integration test runs smoothly

However, if the integration test is executed by gitlab CI, it fails. The only exception I could get is Connection refused.

Can it be that the ports of the service are not exposed properly? How does the CI server determine the ports it has to open to said service?

What might be the problem when running with CI? How can I test it differently?

Sorry for the lot of questions, I'm just hopelessly lost..

Upvotes: 29

Views: 26288

Answers (2)

Sanjay Bharwani
Sanjay Bharwani

Reputation: 4759

I was facing this issue. EXPOSE <port> will work if you own the docker image and in position to update the Dockerfile. In my case, I was to use multiple wiremock images to launch in .gitlab-ci.yml under services section.

services doesn't have any straight way of port mapping like 8080:8080 as in docker-compose.yml.

However there is a work around to pass it as a command as shown below

services:
- name: wiremock/wiremock:main-alpine
  alias: mock-server1
  command: [ "--port","9010","--https-port","9040","--verbose"]
- name: wiremock/wiremock:main-alpine
  alias: mock-server2
  command: [ "--port","9020","--https-port","9050","--verbose"]
- name: wiremock/wiremock:main-alpine
  alias: mock-server3
  command: [ "--port","9030","--https-port","9060","--verbose"]

Please read the GitLab's official document on services, below is the snippet for command option https://docs.gitlab.com/ee/ci/services/

enter image description here

Upvotes: 6

lukket
lukket

Reputation: 145

From the official documentation:

The services keyword defines just another Docker image that is run during your job and is linked to the Docker image that the image keyword defines. This allows you to access the service image during build time.

There is no image keyword in your .gitlab-ci.yml file. Therefore, it's actually unpredictable where your job integration_test runs.

If your job runs inside a Docker container, this container is linked to the container of your service. Links are a legacy feature of Docker, but it's quite similar to two containers that are connected via a separate network. This is quite similar to multiple services in one compose file that communicate with each other.

Everything that is executed in your job's container can access your service via its name or alias (mail.email). Have a look at the Dockerfile of you mail server to see which ports the service listens to:

EXPOSE 25 587 143 465 993 110 995 4190

There is no need to manually expose any ports here. The ports keyword in your compose file exposes ports of a container to your host system. If you do something similar in your CI pipeline, it will expose the ports to the system that runs the job. This is certainly not what you want.

In short: use something like mail.email:993 to connect to your mail server via IMAP from within your CI job.

Upvotes: 10

Related Questions