Поиск по сайту:

Как создавать образы Docker в конвейере GitLab CI


Одним из распространенных вариантов использования конвейеров CI является создание образов Docker, которые вы будете использовать для развертывания своего приложения. GitLab CI — отличный выбор для этого, так как он поддерживает интегрированную службу прокси-сервера, что означает более быстрые конвейеры, и встроенный реестр для хранения ваших созданных образов.

В этом руководстве мы покажем вам, как настроить сборки Docker, которые используют обе вышеуказанные функции. Шаги, которые вам нужно предпринять, немного различаются в зависимости от типа исполнителя GitLab Runner, который вы будете использовать для своего пайплайна. Ниже мы рассмотрим исполнителей Shell и Docker.

Сборка с помощью Shell Executor

Если вы используете исполняющую оболочку, убедитесь, что у вас установлен Docker на компьютере, на котором находится исполняющая программа. Исполнитель работает, выполняя обычные команды оболочки, используя двоичный файл docker на хосте Runner.

Перейдите в репозиторий Git для проекта, для которого вы хотите создать образы. Создайте файл .gitlab-ci.yml в корне репозитория. Этот файл определяет конвейер GitLab CI, который будет запускаться при отправке изменений в ваш проект.

Добавьте в файл следующее содержимое:

stages:
  - build

docker_build:
  stage: build
  script:
    - docker build -t example.com/example-image:latest .
    - docker push example.com/example-image:latest

Этой упрощенной конфигурации достаточно, чтобы продемонстрировать основы конвейерной сборки образов. GitLab автоматически клонирует ваш репозиторий Git в среду сборки, поэтому запуск docker build будет использовать Dockerfile вашего проекта и сделает содержимое репозитория доступным в качестве контекста сборки.

После завершения сборки вы можете docker отправить образ в свой реестр. В противном случае он был бы доступен только для локальной установки Docker, на которой была запущена сборка. Если вы используете частный реестр, сначала запустите docker login, чтобы предоставить правильные данные аутентификации:

script:
  - docker login -u $DOCKER_REGISTRY_USER -p $DOCKER_REGISTRY_PASSWORD

Определите значения двух переменных учетных данных, выбрав «Настройки» > «CI/CD» > «Переменные» в веб-интерфейсе GitLab. Нажмите синюю кнопку «Добавить переменную», чтобы создать новую переменную и присвоить ей значение. GitLab сделает эти переменные доступными в среде оболочки, используемой для запуска вашего задания.

Создание с помощью Docker Executor

Исполнитель Docker GitLab Runner обычно используется для обеспечения абсолютно чистой среды для каждого задания. Задание будет выполняться в изолированном контейнере, поэтому двоичный файл docker на хосте Runner будет недоступен.

Исполнитель Docker предлагает две возможные стратегии для создания образа: либо использовать Docker-in-Docker, либо привязать сокет Docker хоста к среде сборки Runner. Затем вы используете официальный образ контейнера Docker в качестве образа вашего задания, делая команду docker доступной в вашем сценарии CI.

Докер-в-Докере

Использование Docker-in-Docker (DinD) для создания образов дает вам полностью изолированную среду для каждого задания. Процесс Docker, выполняющий сборку, будет дочерним элементом контейнера, который GitLab Runner создает на хосте для выполнения задания CI.

Вам необходимо зарегистрировать исполнитель GitLab Runner Docker с включенным привилегированным режимом, чтобы использовать DinD. Добавьте флаг --docker-privived при регистрации бегуна:

sudo gitlab-runner register -n 
  --url https://example.com 
  --registration-token $GITLAB_REGISTRATION_TOKEN 
  --executor docker 
  --description "Docker Runner" 
  --docker-image "docker:20.10" 
  --docker-volumes "/certs/client" 
  --docker-privileged

В конвейере непрерывной интеграции добавьте образ docker:dind в качестве службы. Это делает Docker доступным в виде отдельного образа, связанного с образом задания. Вы сможете использовать команду docker для создания образов с использованием экземпляра Docker в контейнере docker:dind.

services:
  - docker:dind

docker_build:
  stage: build
  image: docker:latest
  script:
    - docker build -t example-image:latest .

Использование DinD дает вам полностью изолированные сборки, которые не могут влиять ни друг на друга, ни на ваш хост. Основным недостатком является более сложное поведение кэширования: каждое задание получает новую среду, в которой ранее созданные слои не будут доступны. Вы можете частично решить эту проблему, попытавшись получить предыдущую версию вашего образа перед сборкой, а затем использовать флаг сборки --cache-from, чтобы сделать слои извлеченного изображения доступными в качестве источника кеша:

docker_build:
  stage: build
  image: docker:latest
  script:
    - docker pull $CI_REGISTRY_IMAGE:latest || true
    - docker build --cache-from $CI_REGISTRY_IMAGE:latest -t $CI_REGISTRY_IMAGE:latest .

Гнездо для крепления

Установка сокета Docker вашего хоста в среду вашего задания является альтернативным вариантом, когда вы используете исполнителя Docker. Это обеспечивает бесшовное кэширование и избавляет от необходимости добавлять службу docker:dind в конфигурацию CI.

Чтобы настроить это, зарегистрируйте свой Runner с флагом docker-volumes, который привязывает сокет Docker хоста к /var/run/docker.sock внутри контейнеров заданий:

sudo gitlab-runner register -n 
  --url https://example.com 
  --registration-token $GITLAB_REGISTRATION_TOKEN 
  --executor docker 
  --description "Docker Runner" 
  --docker-image "docker:20.10" 
  --docker-volumes /var/run/docker.sock:/var/run/docker.sock

Теперь задания, запускаемые с образом docker, смогут использовать двоичный файл docker как обычно. Операции фактически будут выполняться на вашем хост-компьютере, становясь родственными контейнеру задания, а не дочерними.

Это фактически похоже на использование исполнителя оболочки с установкой Docker на вашем хосте. Изображения будут храниться на хосте, что упрощает использование обычного кэширования слоя docker build.

Хотя этот подход может привести к более высокой производительности, меньшей конфигурации и отсутствию ограничений DinD, он имеет свои уникальные проблемы. Наиболее важными среди них являются последствия для безопасности: задания могут выполнять произвольные команды Docker на вашем хосте Runner, поэтому вредоносный проект в вашем экземпляре GitLab может запускать docker run -it malware-image:latest или docker rm -f $ (docker ps -a) с разрушительными последствиями.

GitLab также предупреждает, что привязка сокетов может вызвать проблемы при одновременном выполнении заданий. Это происходит, когда вы полагаетесь на контейнеры, создаваемые с определенными именами. Если два экземпляра задания выполняются параллельно, второй завершится ошибкой, так как имя контейнера уже существует на вашем хосте.

Вместо этого вам следует рассмотреть возможность использования DinD, если вы ожидаете, что любая из этих проблем будет проблематичной. Хотя DinD больше не рекомендуется, он может иметь больше смысла для общедоступных экземпляров GitLab, которые выполняют параллельные задания CI.

Отправка изображений в реестр GitLab

Проекты GitLab имеют встроенный реестр, который вы можете использовать для хранения своих образов. Вы можете просмотреть содержимое реестра, перейдя в Packages & Registries > Container Registry на боковой панели вашего проекта. Если вы не видите эту ссылку, включите реестр, выбрав «Настройки»> «Основные»> «Видимость, проект, функции и разрешения» и активировав переключатель «Реестр контейнеров».

GitLab автоматически устанавливает переменные среды в ваших заданиях CI, что позволяет вам ссылаться на реестр контейнеров вашего проекта. Настройте раздел script, чтобы войти в реестр и отправить свое изображение:

script:
  - docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY
  - docker build -t $CI_REGISTRY_IMAGE:latest .
  - docker push $CI_REGISTRY_IMAGE:latest

GitLab создает безопасный набор учетных данных для каждого из ваших заданий CI. Переменная среды $CI_JOB_TOKEN будет содержать маркер доступа, который задание может использовать для подключения к реестру в качестве пользователя gitlab-ci-token. URL-адрес сервера реестра доступен как $CI_REGISTRY.

Последняя переменная, $CI_REGISTRY_IMAGE, предоставляет полный путь к реестру контейнеров вашего проекта. Это подходящая основа для ваших тегов изображений. Вы можете расширить эту переменную для создания вложенных репозиториев, таких как $CI_REGISTRY_IMAGE/production/api:latest.

Другие клиенты Docker могут извлекать образы из реестра, аутентифицируясь с помощью токена доступа. Вы можете сгенерировать их на экране «Настройки» > «Токены доступа» вашего проекта. Добавьте область read_registry, затем используйте отображаемые учетные данные для входа в docker в реестр вашего проекта.

Использование прокси-сервера зависимостей GitLab

Прокси-сервер зависимостей GitLab обеспечивает уровень кэширования для исходных изображений, которые вы извлекаете из Docker Hub. Это помогает вам оставаться в пределах ограничений скорости Docker Hub, извлекая содержимое изображений только тогда, когда они действительно изменились. Это также повысит производительность ваших сборок.

Прокси-сервер зависимостей активируется на уровне группы GitLab, выбрав «Настройки» > «Пакеты и реестры» > «Прокси-сервер зависимостей». После его включения добавьте к ссылкам на изображения в файле .gitlab-ci.yml префикс $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX, чтобы получить их через прокси-сервер:

docker_build:
  stage: build
  image: $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX/docker:latest
  services:
    - name: $CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX/docker:dind
      alias: docker

Вот и все! GitLab Runner автоматически входит в реестр прокси-серверов зависимостей, поэтому вам не нужно вручную вводить свои учетные данные.

Теперь GitLab будет кэшировать ваши изображения, повышая производительность и устойчивость к перебоям в работе сети. Обратите внимание, что определение services также пришлось скорректировать — переменные среды не работают со встроенной формой, использовавшейся ранее, поэтому необходимо указать полное имя изображения, а затем команда псевдоним для ссылки в разделе script.

Хотя мы уже настроили прокси для образов, непосредственно используемых на этапах нашей работы, требуется дополнительная работа, чтобы добавить поддержку базового образа в Dockerfile для сборки. Обычная инструкция вроде этой не пройдет через прокси:

FROM ubuntu:latest

Чтобы добавить эту последнюю часть, используйте аргументы сборки Docker, чтобы сделать URL-адрес прокси-сервера зависимостей доступным при пошаговом прохождении Dockerfile:

ARG GITLAB_DEPENDENCY_PROXY
FROM ${GITLAB_DEPENDENCY_PROXY}/ubuntu:latest

Затем измените команду docker build, чтобы определить значение переменной:

script:
  >
    - docker build 
        --build-arg GITLAB_DEPENDENCY_PROXY=${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX} 
        -t example-image:latest .

Теперь ваш базовый образ также будет загружаться через прокси-сервер зависимостей.

Краткое содержание

Сборки образов Docker легко интегрируются в конвейеры GitLab CI. После первоначальной настройки Runner команды docker build и docker push в разделе script вашего задания — это все, что вам нужно для создания образа с Dockerfile в вашем репозитории. Встроенный реестр контейнеров GitLab предоставляет вам личное хранилище для образов вашего проекта.

Помимо базовых сборок, стоит интегрировать прокси-сервер зависимостей GitLab, чтобы повысить производительность и избежать превышения ограничений скорости Docker Hub. Вы также должны проверить безопасность своей установки, оценив, позволяет ли выбранный вами метод ненадежным проектам запускать команды на вашем хосте Runner. Хотя у Docker-in-Docker есть свои проблемы, он является самым безопасным подходом, когда ваш экземпляр GitLab общедоступен или используется большой базой пользователей.




Все права защищены. © Linux-Console.net • 2019-2024