3 мин.

Добавление раннера в GitLab с помощью Docker

У меня есть свой GitLab на отдельном сервере, необходимо к нему прикрутить сборку, тестирование и деплой приложения через GitLab CI и Docker. Избитая тема. Но начинать всё это нужно с того, что необходимо где-то собирать образы. Очевидно это будет сторонний сервер, где будет бегать GitLab Runner. Данное руководство для тех кто хочет быстро это сделать, чтобы приступить уже к сборке приложения. Но вообще есть полная документация на все случаи жизни.

Результатом будет shared runner в своём GitLab, на своём сервере, в своём контейнере.

1. Поднять сервер

Обычно я вручную поднимаю сервер на DigitalOcean сразу с Docker на борту. Там есть возможность one-click установки с нужным ПО. Оч удобно.

Но бывают случаи когда есть сервере (обычно это Ubuntu какая-нибудь), но на нём нет Docker и тогда всё очень просто:

$ curl -sSL https://get.docker.com/ | sh

Эта команда сама установить докер на машину, если его нет. А в том случае, если в процессе вам понадобится и docker-compose, то ещё и так:

$ apt-get update
$ apt-get -y install python-pip
$ pip install docker-compose

Всё, теперь точно имеем сервер c Docker на борту.

2. Запускаем runner

Для начала надо поднять контейнер с раннером на нашем сервере:

$ docker run -d --name gitlab-runner --restart always \
    -v /srv/gitlab-runner/config:/etc/gitlab-runner \
    -v /var/run/docker.sock:/var/run/docker.sock \
    gitlab/gitlab-runner:latest

После непродолжительной развёртки у вас будет готовый контейнер с раннером, который осталось зарегистрировать.

3. Регистрируем runner

Для этого необходимо в контейнере исполнить соответствующую команду и ответить на соответсвующие вопросы с умом, или без ума, но тогда придётся в самом GitLab менять конфигурацию раннера. Я предпочитаю закидывать сразу всё одной командой, чтобы не отвечать на вопросы.

Следующая команда конфигурирует и регистрирует раннер как мне нужно (privileged, locked, tags, etc) сразу без последующих настроек:

$ docker exec -it gitlab-runner gitlab-runner register -n \
    --url "https://gitlab.domain.com" \
    --registration-token token_registration \
    --tag-list docker \
    --executor docker \
    --description "Docker Runner" \
    --docker-image docker:latest \
    --docker-volumes /var/run/docker.sock:/var/run/docker.sock \
    --locked false \
    --docker-privileged

Соответственно, в вашем варианте https://gitlab.domain.com и token_registration будут другие. Последний надо брать со страницы администрирования раннеров в GitLab.

4. Используем runner

Как видно из команды выше, в раннере будут процесситься только джобы помеченные тегом docker в gitlab-ci.yml.

Вот, например, мой простенький ci-конфиг для развёртки с помощью docker-compose всего, что попадает в master-ветку:

variables:
    DOCKER_DRIVER: overlay2
    CI_REGISTRY_IMAGE_WITH_TAG_BY_TAG: "$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME"
    CI_REGISTRY_IMAGE_WITH_TAG_BY_MASTER: "$CI_REGISTRY_IMAGE:latest"

stages:
    - build
    - deploy

build:
    stage: build
    image: docker:latest
    services:
      - docker:dind
    only:
      - master
    tags:
      - docker
    script:
      - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
      - docker build -t $CI_REGISTRY_IMAGE_WITH_TAG_BY_MASTER --no-cache=true .
      - docker push $CI_REGISTRY_IMAGE_WITH_TAG_BY_MASTER

deploy:
    stage: deploy
    image: gitlab/dind:latest
    services:
        - docker:dind
    only:
        - master
    tags:
        - docker
    before_script:
        - mkdir -p ~/.ssh
        - echo "$DEPLOY_SERVER_PRIVATE_KEY" | tr -d '\r' > ~/.ssh/id_rsa
        - chmod 600 ~/.ssh/id_rsa
        - eval "$(ssh-agent -s)"
        - ssh-add ~/.ssh/id_rsa
        - ssh-keyscan -H $DEPLOYMENT_SERVER_IP >> ~/.ssh/known_hosts
    script:
        - scp -r ./docker-compose.yml ./docker-compose.prod.yml root@${DEPLOYMENT_SERVER_IP}:~/
        - ssh root@$DEPLOYMENT_SERVER_IP "docker login -u gitlab-ci-token -p ${CI_JOB_TOKEN} ${CI_REGISTRY}; docker pull ${CI_REGISTRY_IMAGE_WITH_TAG_BY_MASTER}; docker-compose -f docker-compose.yml -f docker-compose.prod.yml stop; docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d"

Соответственно, в вашем проекте обязательно должны быть переменные окружения DEPLOY_SERVER_PRIVATE_KEY и DEPLOYMENT_SERVER_IP, но это уже совсем другая история. Можете для примера почитать про варианты деплоя тут или тут.