Multiple docker-compose files with gitlab shell runner - docker

I am trying to maintain dev, test and master environments on the same host by using Gitlab CI.
.gitlab-ci.yml:
workflow:
rules:
- if: $CI_COMMIT_MESSAGE =~ /-no-ci$/
when: never
- if: $CI_COMMIT_BRANCH == "master"
- if: $CI_COMMIT_BRANCH == "test"
- if: $CI_COMMIT_BRANCH == "dev"
before_script:
- cp /home/gitlab-runner/my-app/.env.$CI_COMMIT_BRANCH ./.env.$CI_COMMIT_BRANCH
- echo '' >> ./.env
- echo 'export CI_COMMIT_BRANCH="${CI_COMMIT_BRANCH}"' >> ./.env.$CI_COMMIT_BRANCH
- "cat .env.$CI_COMMIT_BRANCH | envsubst > .env"
- source .env
- "cat Dockerfile.template | envsubst > Dockerfile"
- rm .env.$CI_COMMIT_BRANCH Dockerfile.template
build-master:
stage: build
script:
- sudo docker-compose build
- sudo docker-compose up -d
only:
- master
tags:
- master
build-test:
stage: build
script:
- sudo docker-compose build
- sudo docker-compose up -d
only:
- test
tags:
- test
build-dev:
stage: build
script:
- sudo docker-compose build
- sudo docker-compose up -d
only:
- dev
tags:
- dev
Since I have to start three containers (webserver, db and pgadmin), I use docker-compose.yml:
version: '3.1'
services:
webserver:
build:
context: ./
restart: always
image: my-app/${CI_COMMIT_BRANCH}
container_name: my-app-webserver-${CI_COMMIT_BRANCH}
volumes:
- ${PATH}:/app/${PATH}
ports:
- ${WEBSERVER_PORT}:${WEBSERVER_PORT}
depends_on:
- db
db:
image: postgres:12.2
restart: always
container_name: my-app-db-${CI_COMMIT_BRANCH}
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- ${HOST_DB_DATA}:/var/lib/postgresql/data
pgadmin:
image: dpage/pgadmin4:4.18
restart: always
container_name: my-app-pgadmin-${CI_COMMIT_BRANCH}
environment:
PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL}
PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD}
PGADMIN_LISTEN_PORT: 80
ports:
- ${PGADMIN_PORT}:80
volumes:
- ${PGADMIN_DATA}:/var/lib/pgadmin/
links:
- "db:pgsql-server"
depends_on:
- db
networks:
default:
name: my-app-network-${CI_COMMIT_BRANCH}
On the host I have /etc/gitlab-runner/config.toml:
concurrent = 1
check_interval = 0
[session_server]
session_timeout = 1800
[[runners]]
name = "my-app-shell-prod"
url = "https://gitlab.my-app.com/"
token = "abcdefgabcdefg"
executor = "shell"
[runners.custom_build_dir]
[runners.cache]
privileged = true
[runners.cache.s3]
[runners.cache.gcs]
[runners.cache.azure]
[[runners]]
name = "my-app-shell-test"
url = "https://gitlab.my-app.com/"
token = "abcdefgabcdefg"
executor = "shell"
[runners.custom_build_dir]
[runners.cache]
privileged = true
[runners.cache.s3]
[runners.cache.gcs]
[runners.cache.azure]
[[runners]]
name = "my-app-shell-dev"
url = "https://gitlab.my-app.com/"
token = "abcdefgabcdefg"
executor = "shell"
[runners.custom_build_dir]
[runners.cache]
privileged = true
[runners.cache.s3]
[runners.cache.gcs]
[runners.cache.azure]
My initial thought was to use three different shell runners with tags master, test and dev to maintain independent builds, for each having a corresponding docker-compose.yml.
When I push to dev, pipeline is passed successfully and I have three containers with names ...-dev running. However, if I merge dev to master, another pipeline is passed, but now I have only three ...-master containers running (but in the same time job logs show that -dev have been restarted).
...
134 $ sudo docker-compose up -d
135 Recreating my-app-db-dev ...
136 Recreating my-app-db-dev ... done
137 Recreating my-app-webserver-dev ...
138 Recreating my-app-pgadmin-dev ...
139 Recreating my-app-pgadmin-dev ... done
140 Recreating my-app-webserver-dev ... done
I found an article on overriding docker-compose.yml files. However, when I try to use -f in .gitlab-ci.yml script section, it shows help message in job logs where no -f option is presented.
# docker-compose -v
docker-compose version 1.29.2, build 5becea4c
The question is: how to maintain docker-compose logic without using -f override.yml? Just create three versions of docker-compose.yml in three folders and use [entrypoint] in .gitlab-ci.yml?
Update
Why do I refuse to use docker:dind? I can not find the right way to run a job that starts docker-in-a-docker since again you need three docker-compose.yml files just to start docker:dind containers. Am I missing something?

Related

cannot mount named volumes from docker-compose in gitlab ci

I am struggling with the CI in gitlab. Namely, I am unable to mount a volume in docker compose.
I am using the shell executor and i dont want to use the docker-in-docker solution, cause i need access to the direct host-system with my project.
I am using the following gitlab-runner configuration:
concurrent = 1
check_interval = 0
shutdown_timeout = 0
[session_server]
session_timeout = 1800
[[runners]]
name = "myRunner"
url = "https://git.#########.com/"
id = 6
token = "#############"
token_obtained_at = 2023-01-18T13:10:20Z
token_expires_at = 0001-01-01T00:00:00Z
executor = "shell"
[runners.custom_build_dir]
[runners.cache]
MaxUploadedArchiveSize = 0
[runners.cache.s3]
[runners.cache.gcs]
[runners.cache.azure]
I want to mount a named volume to the container, this is how i do it in docker-compose.yaml, the named volume "config" should be mounted into the container from docker compose.
# REST-API
rest-api:
image: rest-api
hostname: rest-api
restart: always
build:
context: rest-api
dockerfile: ./Dockerfile
args:
NODE_PARAM: "${NODE_PARAM}"
ports:
- 8080:8080
- 8443:8443
volumes:
- ./rest-api:/usr/src/app
- config:/usr/src/app/config
My pipeline file looks like this:
variables:
COMPOSE_FILE: backend/docker-compose.yml
stages: # List of stages for jobs, and their order of execution
- build
- test
before_script:
- sudo touch /etc/dhcpcd.conf
- sudo touch /etc/systemd/timesyncd.conf
build:
stage: build
script:
- docker compose build
test:
stage: test
script:
- whoami
- docker volume ls
- docker compose up -d --build --pull always
- docker exec -t backend-rest-api-1 ls -la /usr/src/app/
- docker exec -t backend-rest-api-1 npm run test
- docker compose down
This problem only occurs when executing trough gitlab pipeline, executing it manually on the same server is working fine!
executing "docker volume ls" -> Here it shows that the volume config is available.
executing "ls -la /usr/src/app" -> The volume is not mounted, config dir not exists
I am thankful for your help!

gitlab CICD runner in docker container cant use docker commands like docker-compose

I want to create CICD that builds docker image and then compose up this image. My runner is in container as a shell executor, but compose must be on host machine (win10).
my actual gitlab.yaml:
build-job:
image: docker:latest
services:
- docker
before_script:
- docker info
stage: build
script:
- cd ...
- cd ....
- docker-compose build
test-job1:
stage: test
script:
- echo "build worked!"
deploy-prod:
stage: deploy
script:
- cd ...
- cd ....
- docker-compose up
environment: production
and my docker-compose for my runner with auto-registration:
version: '3'
name: Worker
services:
register:
container_name: registration
image: gitlab/gitlab-runner
command:
- register
- --non-interactive
- --locked=false
- --name="...."
- --executor=shell
- --docker-volumes=/var/run/docker.sock:/var/run/docker.sock
- --docker-privileged=true
- --docker-volumes=/certs/client
volumes:
- gitlab-runner-config:/etc/gitlab-runner
- /var/run/docker.sock:/var/run/docker.sock
tty: true
stdin_open: true
restart: "no"
environment:
- CI_SERVER_URL=....
- REGISTRATION_TOKEN=....
labels:
- "traefik.enable=false"
worker:
container_name: ....
image: gitlab/gitlab-runner
volumes:
- /usr/bin/docker:/usr/bin/docker
- gitlab-runner-data:/etc/gitlab-runner
- gitlab-runner-data:/home/gitlab-runner
- gitlab-runner-config:/etc/gitlab-runner
restart: always
volumes:
gitlab-runner-config:
external: true
gitlab-runner-data:
external: true
at the end i get my best result - Cannot connect to the Docker daemon at unix:///var/run/docker.sock (at docker info)
i've tried with //usr or giving full $PATH from env in windows 10,
network_mode changed to "host"
a lot of changes with volumes in compose of registration and runner
How could i get it working or at least enable usage of docker commands?

COPY failed: file not found in build context in GitLab CI/CD pipeline

So I am trying to do docker-compose build from my GitLab CI/CD pipeline by using a docker-compose file but it fails. Trying the same on my PC locally through Windows PowerShell works just fine.
Error in GitLab pipeline
Building spotforus-server
Step 1/4 : FROM openjdk:17
---> 5e28ba2b4cdb
Step 2/4 : WORKDIR /spotforus
---> Using cache
---> 795b15010444
Step 3/4 : COPY build/libs/spotforus-0.0.1-SNAPSHOT.jar /spotforus/spotforus.jar
Service 'spotforus-server' failed to build: COPY failed: file not found in build context or excluded by .dockerignore: stat build/libs/spotforus-0.0.1-SNAPSHOT.jar: file does not exist
Docker-compose file
version: '3.8'
services:
db:
image: mysql:latest
container_name: mysql-db
ports:
- "3306:3306"
restart: always
spotforus-client:
build:
context: ./spotforus-client
dockerfile: Dockerfile
container_name: "spotforus-client"
ports:
- "80:80"
depends_on:
- spotforus-server
spotforus-server:
build: ./spotforus
container_name: spotforus-server
ports:
- "8080:8080"
restart: always
depends_on:
Dockerfile
FROM openjdk:17
WORKDIR /spotforus
COPY build/libs/spotforus-0.0.1-SNAPSHOT.jar /spotforus/spotforus.jar
ENTRYPOINT ["java","-jar","spotforus.jar"]
Gitlab yml file
stages:
- docker
docker:
image:
name: docker/compose:latest
services:
- docker:dind
stage: docker
script:
- docker-compose build
GitLab runner config
concurrent = 1
check_interval = 0
[session_server]
session_timeout = 1800
[[runners]]
name = "Runner"
url = "https://somedomain.gitlab/"
id = 7341
token = "BeNAc2f9gFW-sWX6pewA"
token_obtained_at = 2022-11-08T09:36:30Z
token_expires_at = 0001-01-01T00:00:00Z
executor = "docker"
[runners.custom_build_dir]
[runners.cache]
[runners.cache.s3]
[runners.cache.gcs]
[runners.cache.azure]
[runners.docker]
tls_verify = false
image = "gradle:latest"
privileged = true
disable_entrypoint_overwrite = false
oom_kill_disable = false
disable_cache = false
volumes = ["/cache", "/var/run/docker.sock:/var/run/docker.sock"]
shm_size = 0
I have been reading similar posts here and it seems that the issue is caused by Docker context so I tried tweaking this in my dockerfile and docker-compose but no luck so far.
The issue turned out to be caused by the .gitignore file which was set to exclude .jar and /build. That's why docker-compose build worked just fine locally but failed in the Gitlab pipeline. This comment really helped me to understand how to create exceptions in .gitignore.

Mounting a volume with gitlab docker:dind services

I have an issue with gitlab runner using docker:dind service.
I'm trying to run a docker-compose file with simple volume on a job, here the job :
test_e2e:
image: tmaier/docker-compose
stage: test
services:
- docker:dind
variables:
GIT_STRATEGY: none
GIT_CHECKOUT: "false"
DOCKER_DRIVER: overlay2
before_script:
- ls
script:
- cp .env.dist .env
- docker-compose -f docker-compose.yml -f docker-compose-ci.yml up -d
The job start normally but a container in docker-compose-ci.yml doesn't seem to mount the volume as specified in it, here docker-compose-ci.yml
version: '3.3'
services:
wait_app:
image: dadarek/wait-for-dependencies
networks:
- internal
depends_on:
- traefik
- webapp
command: webapp:3000
cypress:
# the Docker image to use from https://github.com/cypress-io/cypress-docker-images
image: "cypress/included:6.5.0"
networks:
- internal
depends_on:
- traefik
- webapp
- api
- mysql
- redis
environment:
# pass base url to test pointing at the web application
- CYPRESS_baseUrl=http://app.localhost:3000
working_dir: /cypress
volumes:
- ./cypress/:/cypress
Here if I make an "docker exec app_cypress_1 sh -c "ls -al" || 1" of /cypress folder inside the container cypress, I will have nothing even though I do have files in there on the host.
But I tried on a different version of the runner 13.7.0 instead of 13.5.0, and it work as expected.
Where could be the issue ? Is it the gitlab runner are maybe there is another parameter that I can change to make it work ?
Thank you

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