Reputation: 1015
I'm trying to run a continuous integration in GitLab CI consisting of:
Those are running inside one job. I can do it without any problem until come up some test that needs to communicate with database. My container can't communicate with Postgres services defined.
I've reproduce it in a public repository with simple ping
script
image: docker:stable
services:
- docker:dind
- postgres:latest
job1:
script:
- ping postgres -c 5
- docker run --rm --network="host" alpine:latest sh -c "ping postgres -c 5"
The first script could run without any problem, but the second one failed with error
ping: bad address 'postgres'
How can I access the service?
Or should I run the test in a different job?
Upvotes: 7
Views: 1758
Reputation: 1517
You can simply use docker compose
for this.
Create a Docker Compose file .gitlab/docker-compose.yml
:
services:
test-runner:
image: alpine:latest
depends_on:
- postgres
postgres:
image: postgres:latest
environment:
POSTGRES_DB: "${POSTGRES_DB:?}"
POSTGRES_USER: "${POSTGRES_USER:?}"
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD:?}"
And your CI job can look like this:
test:
stage: test
image: docker
services:
- docker:dind
variables:
COMPOSE_FILE: .gitlab/docker-compose.yml
POSTGRES_DB: postgres
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
script:
- docker compose run test-runner sh -c "ping postgres -c 5"
Upvotes: 0
Reputation: 307
The solution is to use --add-host=postgres:$POSTGRES_IP
to pass over the ip address present in job container.
To find out postgres ip linked to the outer container you can use for example getent hosts postgres | awk '{ print $1 }'
So the yml would look like
image: docker:stable
services:
- docker:dind
- postgres:latest
job1:
script:
- ping postgres -c 5
- docker run --rm --add-host=postgres:$(getent hosts postgres | awk '{ print $1 }') alpine:latest sh -c "ping postgres -c 5"
To understand why the other more common ways to connect containers wont work in this case, we have to remember we are trying to link a nested container with a service linked to its "parent". Something like this:
gitlab ci runner --> docker -> my-container (alpine)
-> docker:dind
-> postgres
So we are trying to connect a container with its "uncle". Or connecting nested containers
As noted by @tbo, using --network host
will not work. This is probably because gitlab ci use --link
(as explained here) to connect containers instead of the newer --network
. The way --link
works makes that the services containers are connected to the job container, but not connected with one another. So using host network wont make the nested container inherit postgres hostname.
One could also think that using --link postgres:postgres
would work, but it also won't as in this environment postgres is only a hostname with the ip of the container outside. There is not container here to be linked with the nested container
So all we can do is manually add a host with the correct ip to the nested container using --add-host
as explained above.
Upvotes: 5