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..
Exposing ports is a way of documenting which ports are used, but does not actually map or open any ports. Exposing ports is optional. You publish ports using the --publish or --publish-all flag to docker run . This tells Docker which ports to open on the container's network interface.
There are several ways to do this: you can expose a port via the --expose flag at runtime, or include an EXPOSE instruction in the Dockerfile. You can also publish ports by using the -p or -P flags in the Docker run string.
You can expose a port through your Dockerfile or use --expose and then publish it with the -P flag. This will bind the exposed port to your Docker host on a random port (verified by running docker container ls ). You can expose a port through your Dockerfile or use --expose and then publish it with the -p 80:80 flag.
First, pull the image down to your host with docker pull. Now, use docker image inspect to see which ports this image has exposed. By passing it a format string, you can have inspect filter everything except the published ports. Just as you would expect, Nginx is listening on port 80.
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 theimage
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With