Connecting to a service from a Gitlab CI job - docker

I am attempting to run e2e tests in the gitlab ci that use a React frontend, Java Spring backend and PostgreSQL.
The relevant pieces of the .gitlab-ci -config are as follows:
variables:
IMAGE_NAME: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
FF_NETWORK_PER_BUILD: 1
docker-backend-build:
image: docker:latest
services:
- docker:dind
stage: package
dependencies:
- backend-build
script:
- docker build -t registry.gitlab.com/repo-name .
- docker tag registry.gitlab.com/repo-name $IMAGE_NAME
- docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN registry.gitlab.com
- docker push $IMAGE_NAME
end-to-end-test:
stage: integration-test
image: node:latest
services:
- name: postgres:9.6
- name: $IMAGE_NAME
alias: backend
variables:
DB_USERNAME: postgres
DB_PASSWORD: postgres
JDBC_CONNECTION_STRING: 'jdbc:postgresql://postgres:5432/database?stringtype=unspecified'
dependencies:
- frontend-build
script:
- cd frontend
- yarn start:ci & ./node_modules/wait-on/bin/wait-on http://backend:9070/api/health http://localhost:3000
- yarn run cy:run
artifacts:
when: always
paths:
- frontend/cypress/videos/*.mp4
- frontend/cypress/screenshots/**/*.png
expire_in: 1 day
The Dockerfile for the backend is as follows:
FROM tomcat:latest
ADD backend/target/server.war /usr/local/tomcat/webapps/
RUN sed -i 's/port="8080"/port="9070"/' /usr/local/tomcat/conf/server.xml
EXPOSE 9070
CMD ["catalina.sh", "run"]
The server.war is created on an earlier stage in the CI-pipeline.
The server.war is set to listen to port 9070, and the Dockerfile succesfully changes the Tomcat port to 9070 as well. The Tomcat instance is able to connect to the postgres instance via postgres:5432 because of the FF_NETWORK_PER_BUILD -flag, but for some reason this script hangs on the wait-on http://backend:9070/api/health command forever. It can not connect to backend:9070 even though the server is up and running. (and the health-endpoint exists). The server doesn't receive any indication that it is trying to be connected to.
What could I be doing wrong? I also tried to connect to http://localhost:9070/api/health but that didn't work either.

The answer for me was simply changing the Dockerfile as follows:
- ADD backend/target/server.war /usr/local/tomcat/webapps/
+ ADD backend/target/server.war /usr/local/tomcat/webapps/ROOT.war
because without that, the server was actually listening in http://backend:9070/api/health/server. Silly me.

Related

Gitlab-ci service command not running

I'm trying to spin up my backend image to use for e2e-testing. When building the backend I make an image which can be used for a service in the frontend. My .gitlab-cy.yml looks partly likes this:
build-test:
stage: build
script:
- docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN registry.gitlab.com
- docker build --build-arg BUILD_ARGUMENT_ENV=test --build-arg BUILD_ARGUMENT_DEBUG_ENABLED=true -t registry.gitlab.com/<company>/<repo>/test:latest .
- docker push registry.gitlab.com/<company>/<repo>/test:latest
only:
changes:
- Dockerfile
- docker-compose.yml
- .gitlab-ci.yml
- docker/*
- .env.citest
when: manual
tags:
- test
The job in the front-end looks like this:
e2e-testing:
image: cypress/browsers:node16.14.2-slim-chrome100-ff99-edge
services:
- name: registry.gitlab.com/<company>/<repo>/test:latest
alias: <company>-backend
command: [
"php artisan db:seed"
]
- name: postgis/postgis:12-3.3
alias: postgres_citest
- name: redis:5.0.9
alias: redis_citest
variables:
POSTGRES_DB: <company>_citest
POSTGRES_USER: <company>
POSTGRES_PASSWORD: secret
REDIS_PORT: 6379
stage: testing
before_script:
- yarn
- yarn run dev &
script:
- yarn run e2e:record --parallel --env IS_CI_RUNNING=true
artifacts:
when: always
paths:
- cypress/videos/**/*.mp4
- cypress/screenshots/**/*.png
expire_in: 1 day
tags:
- test
The command php artisan db:seed isn't preformed and I get the following error:
exec: php artisan db:seed: not found
The other services are used by the backend so I figured they need to be spin up as well. How do I get the command working?
Edit: I've tried testing it local and it does work if I go to the right folder cd ../base, so I added this to the command, but it makes no difference. It still says it can't find the command
Edit 2: I overlooked an error and it seems te gitlab runner is not running. Stil don't know how to solve this
Error response from daemon: Cannot link to a non running container

Gitlab CI can't establish connection on port that docker is running

I spent a whole day to this point, still struggling, the error says "Failed to connect to localhost port 9000 after".
I have a Nodejs app, which uses Postgres as DB. I was able to connect them together. And, the app runs in attach mode very well. When, I run it on de-attach mode, and curl it, I get the error. I even put a long time sleep to make sure it has enough time to start the docker but still failed to connect to the port
The main line is how I run the docker, and get Postgres as a service. I have checked the health of the service. I am not sure if this is a firewall or networking issue i.e. the interfaces here.
- docker run -d -e POSTGRES_HOST=$POSTGRES_PORT_5432_TCP_ADDR -p 9000:9000 $DOCKER_TEST_IMAGE_API
image: docker:19.03.12
stages:
- build
- test
variables:
DOCKER_HOST: tcp://docker:2376
DOCKER_TLS_CERTDIR: "/certs"
DOCKER_DRIVER: overlay2
DOCKER_TEST_IMAGE_API: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
DOCKER_RELEASE_IMAGE_API: $CI_REGISTRY_IMAGE
before_script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
api-component-api:
stage: build
services:
- docker:19.03.12-dind
variables:
PORT: '9000'
script:
- docker build --pull -t $DOCKER_TEST_IMAGE_API api/.
- docker push $
enter code here
api-component-api:
stage: build
services:
- docker:19.03.12-dind
variables:
PORT: '9000'
script:
- docker build --pull -t $DOCKER_TEST_IMAGE_API api/.
- docker push $DOCKER_TEST_IMAGE_API
api-component-tests:
stage: test
services:
- name: 'postgres:11.9'
alias: postgres
- name: 'docker:19.03.12-dind'
alias: docker
variables:
# POSTGRES Service
POSTGRES_USER: 'postgres'
POSTGRES_PASSWORD: 'password'
POSTGRES_DB: 'postgres'
POSTGRES_HOST: 'postgres'
POSTGRES_HOST_AUTH_METHOD: trust
script:
- env | grep POSTGRES_PORT_5432_TCP_ADDR
- docker run -d -e POSTGRES_HOST=$POSTGRES_PORT_5432_TCP_ADDR -p 9000:9000 $DOCKER_TEST_IMAGE_API
- sleep 60
- docker ps -a
- docker network ls
- curl -X GET "http://localhost:9000/rooms/1000ef5c-1657-46b2-bb36-c74080e00c01"
- cd end-to-end-tests
- yarn install
- yarn test
Digest: sha256:f8d84da7264faf570184929a441e448d680ccbfd297bcd0aef0d7f455c360614
Status: Downloaded newer image for registry.gitlab.com/.../simple-room-booking:main
f24ef88e36e16beb7f32acb03f7cda5775742b6639232a9692e4ef494fe22e93
$ sleep 60
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f24ef88e36e1 registry.gitlab.com/.../simple-room-booking:main "docker-entrypoint.s…" About a minute ago Up About a minute 0.0.0.0:9000->9000/tcp lucid_yalow
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
c7d6ee26e52e bridge bridge local
6760c4e13b56 host host local
3bb3bbf3cd42 none null local
$ curl -X GET "http://localhost:9000/rooms/1000ef5c-1657-46b2-bb36-c74080e00c01"
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
curl: (7) Failed to connect to localhost port 9000 after 6 ms: Connection refused
Cleaning up project directory and file based variables
00:01
ERROR: Job failed: exit code 7
I do not have much experience with GitLab.
I did spend two days on this. The problem was from networking between the docker.
Source: https://docs.gitlab.com/ee/ci/services/#using-services-with-docker-run-docker-in-docker-side-by-side
variables:
FF_NETWORK_PER_BUILD: "true" # activate container-to-container networking
This works after some refactoring, but the main piece was this feature flag.
api-component-tests:
stage: test
services:
- name: 'postgres:11.9'
alias: postgres
- name: 'docker:19.03.12-dind'
alias: docker
- name: $DOCKER_TEST_IMAGE_API
alias: api
variables:
# POSTGRES Service
POSTGRES_USER: 'postgres'
POSTGRES_PASSWORD: 'password'
POSTGRES_DB: 'postgres'
POSTGRES_HOST: 'postgres'
POSTGRES_HOST_AUTH_METHOD: trust # activate container-to-container networking
# API Service
POSTGRES_DSN: 'postgresql://postgres/postgres?sslmode=disable&user=postgres&password=password'
FF_NETWORK_PER_BUILD: "true"
script:
- apk --update add postgresql-client
- apk add nodejs yarn curl
- sleep 10
- curl -X GET "http://api:9000/rooms/1000ef5c-1657-46b2-bb36-c74080e00c01"
- cd end-to-end-tests
- export apiBaseUrl='http://api:9000'
- yarn install
- yarn test
Gitlab piepline + docker : (7) Failed to connect to localhost port 9000: Connection refuse
I had the same issue. Please see the last answer. it worked very nice for me.

Elixir Testing with Docker-Compose UP

I've created a simple Sonatype API client in Elixir that returns the repositories and the components of the repositories.
I now need to create tests in Elixir so that I can verify the repo. I am using docker-compose to start the sonatype container. I need the tests to start with a fresh Docker(sonatype) repo to work with, via docker-compose up, then verify that it doesn't have any containers in it. Then from there add one or more images, then validate that the images I added are present. As cleanup, I could delete those images. It must be an automated set of tests that can run in CI or a user can run on their local machine.
My question is how would I be able to do that by either a .exs test file or bash script file?
You can build a docker-compose.yml file with something similar to this:
version: "2.2"
services:
my_app:
build:
context: .
ports:
- 4000:4000
command: >
bash -c 'wait-for-it -t 60 sonatype:1234
&& _build/prod/rel/my_app/bin/my_app start'
tests:
extends:
service: my_app
environment:
MIX_ENV: test
LOG_LEVEL: "warn"
working_dir: /my_app
depends_on:
- sonatype
command:
bash -c 'mix test'
sonatype:
image: sonatype/nexus3:3.19.1
ports:
- "1234:1234"
Then you have a bash script like test.sh:
docker-compose build tests
docker-compose run tests
EXIT=$?
docker-compose down --volumes
exit $EXIT
I'm not familiar with Sonatype, so this might not make sense, and you need to adapt.

How to set proxy in docker-in-docker (dind) in gitlab CI

I am trying to set up a job with gitlab CI to build a docker image from a dockerfile, but I am behind a proxy.
My .gitlab-ci.yml is as follows:
image: docker:stable
variables:
DOCKER_HOST: tcp://docker:2375
DOCKER_DRIVER: overlay2
HTTP_PROXY: $http_proxy
HTTPS_PROXY: $http_proxy
http_proxy: $http_proxy
https_proxy: $http_proxy
services:
- docker:dind
before_script:
- wget -O - www.google.com # just to test
- docker search node # just to test
- docker info # just to test
build:
stage: build
script:
- docker build -t my-docker-image .
wget works, meaning that proxy setup is correct, in theory
But the commands docker search, docker info and docker build do not work, apparently because of a proxy issue.
An excerpt from the job output:
$ docker search node
Warning: failed to get default registry endpoint from daemon (Error response from daemon:
[and here comes a huge raw HTML output including the following message: "504 - server did not respond to proxy"]
It appears docker does not read from the environment variables to setup proxy.
Note: I am indeed using a runner in --privileged mode, as the documentation instructs to do.
How do I fix this?
If you want to be able to use docker-in-docker (dind) in gitlab CI behind proxy, you will also need to setup no_proxy variable in your gitlab-ci.yml file. NO_PROXY for host "docker".
This is the gitlab-ci.yml that works with my dind:
image: docker:19.03.12
variables:
DOCKER_TLS_CERTDIR: "/certs"
HTTPS_PROXY: "http://my_proxy:3128"
HTTP_PROXY: "http://my_proxy:3128"
NO_PROXY: "docker"
services:
- docker:19.03.12-dind
before_script:
- docker info
build:
stage: build
script:
- docker run hello-world
Good luck!
Oddly, the solution was to use a special dind (docker-in-docker) image provided by gitlab instead, and it works without setting up services and anything. The .gitlab-ci.yml that worked was as follows:
image: gitlab/dind:latest
before_script:
- wget -O - www.google.com
- docker search node
- docker info
build:
stage: build
script:
- docker build -t my-docker-image .
Don't forget that the gitlab-runner must be registered with the --privileged flag.
I was unable to get docker-in-docker (dind) working behind our corporate proxy.
In particular, even when following the instructions here a docker build command would still fail when executing FROM <some_image> as it was not able to download the image.
I had far more success using kaniko which appears to be Gitlabs current recommendation for doing Docker builds.
A simple build script for a .NET Core project then looks like:
build:
stage: build
image: $BUILD_IMAGE
script:
- dotnet build
- dotnet publish Console--output publish
artifacts:
# Upload all build artifacts to make them available for the deploy stage.
when: always
paths:
- "publish/*"
expire_in: 1 week
kaniko:
stage: dockerise
image:
name: gcr.io/kaniko-project/executor:debug
entrypoint: [""]
script:
# Construct a docker-file
- echo "FROM $RUNTIME_IMAGE" > Dockerfile
- echo "WORKDIR /app" >> Dockerfile
- echo "COPY /publish ." >> Dockerfile
- echo "CMD [\"dotnet\", \"Console.dll\"]" >> Dockerfile
# Authenticate against the Gitlab Docker repository.
- echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
# Run kaniko
- /kaniko/executor --context . --dockerfile Dockerfile --destination $CI_REGISTRY_IMAGE:$VersionSuffix

Docker Compose based Gitlab CI - Pipe error

The problem
I have made a project with docker compose. It works well on localhost. I want to use this base to test or analyze code with Gitlab Runner. I solved a lot of problems, like install docker compose, run and build selected containers and run commands in container. The first job ran and success (!!!), but the following jobs failed before "before_script":
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
...
Error response from daemon: Conflict.
...
Error response from daemon: Conflict.
I don't understand why. What do I do wrong? I repeat: the first job of the pipeline runs well with "success" message! Each other jobs of the pipeline fail.
Full output:
Running with gitlab-ci-multi-runner 9.4.0 (ef0b1a6)
on XXX Runner (fdc0d656)
Using Docker executor with image docker:latest ...
Starting service docker:dind ...
Pulling docker image docker:dind ...
Using docker image docker:dind ID=sha256:5096e5a0cba00693905879b09e24a487dc244b56e8e15349fd5b71b432c6ec9ffor docker service...
ERROR: Preparation failed: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
Will be retried in 3s ...
Using Docker executor with image docker:latest ...
Starting service docker:dind ...
Pulling docker image docker:dind ...
Using docker image docker:dind ID=sha256:5096e5a0cba00693905879b09e24a487dc244b56e8e15349fd5b71b432c6ec9f for docker service...
ERROR: Preparation failed: Error response from daemon: Conflict. The container name "/runner-fdc0d656-project-35-concurrent-0-docker" is already in use by container "80918876ffe53e33ce1f069e6e545f03a15469af6596852457f11dbc7a6c5b58". You have to remove (or rename) that container to be able to reuse that name.
Will be retried in 3s ...
Using Docker executor with image docker:latest ...
Starting service docker:dind ...
Pulling docker image docker:dind ...
Using docker image docker:dind ID=sha256:5096e5a0cba00693905879b09e24a487dc244b56e8e15349fd5b71b432c6ec9f for docker service...
ERROR: Preparation failed: Error response from daemon: Conflict. The container name "/runner-fdc0d656-project-35-concurrent-0-docker" is already in use by container "80918876ffe53e33ce1f069e6e545f03a15469af6596852457f11dbc7a6c5b58". You have to remove (or rename) that container to be able to reuse that name.
Will be retried in 3s ...
ERROR: Job failed (system failure): Error response from daemon: Conflict. The container name "/runner-fdc0d656-project-35-concurrent-0-docker" is already in use by container "80918876ffe53e33ce1f069e6e545f03a15469af6596852457f11dbc7a6c5b58". You have to remove (or rename) that container to be able to reuse that name.
Files
.gitlab-ci.yml
# Select image from https://hub.docker.com/r/_/php/
image: docker:latest
# Services
services:
- docker:dind
stages:
- build
- test
- deploy
cache:
key: ${CI_BUILD_REF_NAME}
untracked: true
paths:
- vendor
- var
variables:
DOCKER_CMD: docker exec --user user bin
COMPOSE_HTTP_TIMEOUT: 300
before_script:
- apk add --no-cache py-pip bash
- pip install docker-compose
- touch ~/.gitignore
- bin/docker-init.sh
- cp app/config/parameters.gitlab-ci.yml app/config/parameters.yml
- cp app/config/nodejs_parameters.yml.dist app/config/nodejs_paramteres.yml
- chmod -R 777 app/cache app/logs var
# Load only binary and mysql
- docker-compose up -d binary mysql
build:
stage: build
script:
- ${DOCKER_CMD} composer install -n
- ${DOCKER_CMD} php app/console doctrine:database:create --env=test --if-not-exists
- ${DOCKER_CMD} php app/console doctrine:migrations:migrate --env=test
codeSniffer:
stage: test
script:
- ${DOCKER_CMD} bin/php-cs-fixer fix --dry-run --config-file=.php_cs
database:
stage: test
script:
- ${DOCKER_CMD} php app/console doctrine:mapping:info --env=test
- ${DOCKER_CMD} php app/console doctrine:schema:validate --env=test
- ${DOCKER_CMD} php app/console doctrine:fixtures:load --env=test
unittest:
stage: test
script:
- ${DOCKER_CMD} bin/phpunit -c app --debug
deploy_demo:
stage: deploy
script:
- echo "Deploy to staging server"
environment:
name: staging
url: https://staging.example.com
only:
- develop
deploy_prod:
stage: deploy
script:
- echo "Deploy to production server"
environment:
name: production
url: https://example.com
when: manual
only:
- master
docker-compose.yml
version: "2"
services:
web:
image: nginx:latest
ports:
- "${HTTP_PORT}:80"
depends_on:
- mysql
- elasticsearch
- binary
links:
- binary:php
volumes:
- ".:/var/www"
- "./app/config/docker/vhost.conf:/etc/nginx/conf.d/site.conf"
- "${BASE_LOG_DIR}/nginx:/var/log/nginx"
mysql:
image: mysql:5.6
environment:
MYSQL_USER: test
MYSQL_PASSWORD: test
MYSQL_ROOT_PASSWORD: test
ports:
- "${MYSQL_PORT}:3306"
volumes:
- "${BASE_LOG_DIR}/mysql:/var/log/mysql"
- "${BASE_MYSQL_DATA_DIR}:/var/lib/mysql"
- "./app/config/docker/mysql.cnf:/etc/mysql/conf.d/mysql.cnf"
elasticsearch:
image: elasticsearch:1.7.6
ports:
- "${ELASTICSEARCH_PORT}:9200"
volumes:
- "${BASE_ELASTICSEARCH_DATA_DIR}:/usr/share/elasticsearch/data"
binary:
image: fchris82/kunstmaan-test
container_name: bin
volumes:
- ".:/var/www"
- "${BASE_LOG_DIR}/php:/var/log/php"
- "~/.ssh:/home/user/.ssh"
tty: true
environment:
LOCAL_USER_ID: ${LOCAL_USER_ID}
config.toml
[[runners]]
name = "XXX Runner"
url = "https://gitlab.xxx.xx/"
token = "xxxxxxxxxxx"
executor = "docker"
[runners.docker]
tls_verify = false
image = "docker:latest"
privileged = true
disable_cache = false
volumes = ["/var/run/docker.sock:/var/run/docker.sock", "/cache"]
shm_size = 0
[runners.cache]
OK, I found the problem. I spoilt the configuration. If you use dind service in .gitlab-ci.yml then don't use /var/run/docker.sock volume in config.toml file OR vica versa if you use "socket" method, don't use the dind service.
More informations: https://docs.gitlab.com/ce/ci/docker/using_docker_build.html

Resources