Довольно часто мы используем GitLab CI для докеризации наших приложений. Но как запустить контейнер Docker из GitLab Container Registry? Можно ли использовать Docker Compose? Делимся переводом статьи, в которой автор отвечает на эти вопросы, и рассказывает о функции services keyword в GitLab CI. Она позволяет запустить один или несколько образов Docker и связать их с вашим заданием.

Перед началом
Для этого сценария я создал приложение Node.js, которое предоставляет API.

Таким образом, текущий пайплайн состоит из следующих этапов:
-
build, где устанавливаются все зависимости -
test, на котором выполняются все модульные тесты -
package, где приложение докеризируется, и образ отправляется в GitLab Container Registry.
Для справки, вот как выглядит .gitlab-ci.yml на этом этапе:
stages: - build - test - package build: stage: build image: node:14-alpine script: - npm ci --only=production artifacts: paths: - node_modules/ - server.js unit tests: stage: test image: node:14-alpine before_script: - npm install script: - npm test build docker image: stage: package image: docker services: - docker:dind script: - echo $CI_REGISTRY_PASSWORD | docker login -u $CI_REGISTRY_USER $CI_REGISTRY --password-stdin - docker build -t $CI_REGISTRY_IMAGE . - docker push $CI_REGISTRY_IMAGE
В этом сценарии используется shared runner инфраструктура GitLab.com, где GitLab раннеры используют Kubernetes executor.
Для некоторых Docker executor может потребоваться указать переменную DOCKER_HOST. Вы узнаете об этом, если получите эту ошибку:
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
Этот подход НЕ подходит для shell executors.
variables: DOCKER_HOST: tcp://docker:2375/
или
variables: DOCKER_HOST: tcp://docker:2376/
Проблема
Следующим логичным шагом было бы проведение приемочных тестов, выполнение нескольких команд cURL в контейнере Docker или, что еще лучше, использование Postman/Newman для тестирования API.
Как же запустить Docker-контейнер в рамках конвейера GitLab CI?
Запуск контейнера с помощью docker run
Локально я собрал и протестировал контейнер с помощью docker build и docker run. То же самое должно быть возможно и в рамках конвейера, верно?
Задание build docker image уже предоставляет очень хороший шаблон для использования Docker в GitLab. Поэтому я войду в GitLab Container Registry и запущу созданный ранее образ.
Чтобы упростить конвейер, я НЕ указывал никаких версий для образов docker и docker:dind и не создавал никаких тегов для созданного образа. В реальном сценарии я бы сделал и то, и другое.
stages: - build - test - package - acceptance ... curl api testing: stage: acceptance image: docker services: - docker:dind script: - echo $CI_REGISTRY_PASSWORD | docker login -u $CI_REGISTRY_USER $CI_REGISTRY --password-stdin - docker run -d -p 3000:3000 $CI_REGISTRY_IMAGE - apk add curl - curl http://localhost:3000/status | grep "UP"
К сожалению, следующая установка завершится с ошибкой:
curl: (7) Failed to connect to localhost port 3000 after 5 ms: Connection refused

Но почему? Локально все работало просто отлично. Чтобы объяснить причину, позвольте мне познакомить вас с сервисами GitLab CI.
Что такое GitLab CI services?
Как вы видели, задание, создающее конвейер, использовало ключевое слово services для указания образа docker:dind.
В двух словах, сервисы GitLab предоставляют вам возможность запускать дополнительные контейнеры Docker и связывать их с вашим образом (тем, который вы указали в ключевом слове image).
Один из наиболее типичных случаев использования — когда вам нужна база данных, API или другой сервис, который можно вызвать по сети.
Вот несколько ключевых аспектов, которые вам необходимо запомнить:
-
Образ или образы, указанные в services, могут быть доступны только через сетевое соединение.
-
Образ или образы, указанные в services, должны открывать службу на заданном порту. В противном случае они бесполезны в данном контексте.
-
Вы не сможете подключаться или выполнять команды командной строки на контейнерах, запущенных как службы.
-
Использование сервисов НЕ похоже на определение файла
docker-compose.yaml
Зачем dockerу нужен docker:dind в качестве сервиса?
Если у вас локально установлен Docker, вы можете открыть окно терминала и ввести команду, например:
docker --version
На выходе получится что-то вроде

Однако если я попытаюсь выполнить такие команды, как docker pull, docker build или docker run, то получу ошибку, подобную этой:
Error response from daemon: dial unix docker.raw.sock: connect: connection refusedCannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
На этом этапе позвольте мне процитировать документацию Docker:
Docker использует клиент-серверную архитектуру. Клиент Docker общается с демоном Docker, который выполняет всю работу по созданию, запуску и распространению ваших контейнеров Docker. Клиент Docker и демон могут работать в одной системе, или вы можете подключить клиента Docker к удаленному демону Docker. Клиент Docker и демон взаимодействуют с помощью REST API, через сокеты UNIX или сетевой интерфейс.
На локальном уровне вы не задумываетесь об этом, поскольку и клиент, и демон установлены на одной машине. Но в GitLab все обстоит несколько иначе.
Итак, в GitLab образ docker — это просто клиент. Образ docker:dind — это демон Docker, который запускается как служба, предлагая доступные по сети сервисы. Клиент может взаимодействовать с демоном через сетевой интерфейс.
Доступ к контейнеру Docker, запущенному как служба
В предыдущем примере приложение Node.js, открывающее API на порту 3000, было запущено демоном Docker в контейнере docker:dind.
Поэтому использование localhost не сработает, так как API запущен в другом контейнере. К счастью, GitLab автоматически генерирует имя хоста для соответствующей службы. В данном случае это имя хоста — docker.
Поэтому мы можем получить доступ к приложению с помощью cURL, адаптировав команду для использования docker вместо localhost.
curl http://docker:3000/status | grep "UP"

Однако такой подход громоздок, поскольку теперь мы запускаем Docker в Docker в Docker. Время выполнения только этого задания составляет 61 секунду. Должен быть лучший способ.
Запуск частного контейнера Docker с помощью GitLab services
Ключевое слово services позволяет нам указать как публичный образ Docker, доступный на Dockerhub, так и использовать наш частный GitLab Container Registry.
curl api testing:
stage: acceptance
image: curlimages/curl
services:
— name: $CI_REGISTRY_IMAGE
alias: banking-api
script:
— curl http://banking-api:3000/status | grep «UP»
Я расширил конфигурацию, указав alias. Я не был уверен, какое имя хоста сгенерирует GitLab, и предпочел указать его самостоятельно.
Запуск приемочных тестов Postman/Newman на основе образа Docker
Следуя принципам, использованным в cURL, я могу добавить новое задание, которое использует публичный образ Newman Docker для запуска существующей коллекции Postman.
postman api testing: stage: acceptance image: name: postman/newman entrypoint: [""] services: - name: $CI_REGISTRY_IMAGE alias: banking-api script: - newman run test/collection.json --env-var "baseUrl=banking-api:3000"
Обратите внимание, что я ввел переменную окружения Postman baseUrl во время выполнения.
Устранение неполадок
Не удается подключиться к демону Docker по адресу unix:///var/run/docker.sock. Запущен ли демон Docker?
Для некоторых исполнителей Docker может потребоваться указать переменную DOCKER_HOST на уровне конвейера или задания.
variables: DOCKER_HOST: tcp://docker:2375/
или
variables: DOCKER_HOST: tcp://docker:2376/
Заключение
Надеюсь, это руководство помогло вам получить доступ к вашему приложению dockerize из вашего CI-конвейера GitLab.
Полезные ссылки:
Окунись в мир практических задач по CI/CD, пополни портфолио реальными кейсами и вырасти до нового уровня в своей профессии на Навыкуме по CI/CD в Слёрме.
Навыкум позволит тебе:
-
Наработать около 20 часов практики.
-
Добавить в своё резюме и базовые, и реальные кейсы по CI/CD.
-
«Подсмотреть» лучшие практики в свою копилку знаний.
-
Попасть в комьюнити сильных специалистов с чатом поддержки. Доступ к нему навсегда.
ссылка на оригинал статьи https://habr.com/ru/articles/778652/
Добавить комментарий