Интеграция Docker в CI/CD-пайплайны

Мы подошли к этапу, который превращает разрозненные инструменты в единую систему. До этого момента мы научились писать Dockerfile для упаковки приложений и работать с переменными GitLab CI/CD для защиты данных. Теперь наша задача — объединить эти навыки, чтобы при каждом обновлении кода система автоматически создавала актуальный образ и сохраняла его в надежном месте.

В современной разработке ручная сборка и отправка образов с локальной машины — это риск. Можно забыть обновить зависимости, использовать не ту версию базового образа или оставить лишние файлы в слоях. Автоматизация гарантирует, что в продакшн попадет именно тот код, который прошел проверку в репозитории.

Реестр контейнеров: хранилище образов

Прежде чем запускать сборку, нужно определить, куда мы отправим результат. Реестр контейнеров (Container Registry) — это специализированное хранилище для Docker-образов. В GitLab есть встроенный реестр, интегрированный с правами доступа к проекту.

Для взаимодействия с реестром в пайплайне нужны три команды:

  1. docker login — авторизация в хранилище.
  2. docker build — создание образа из Dockerfile.
  3. docker push — отправка готового образа в реестр.

Мы не прописываем логины и пароли в коде. GitLab автоматически предоставляет временные переменные для каждой задачи: $CI_REGISTRY_USER и $CI_JOB_TOKEN.

Технология Docker-in-Docker

Когда задача в GitLab Runner запускается внутри Docker-контейнера, возникает сложность: как запустить Docker внутри Docker? Эта технология называется Docker-in-Docker (или сокращенно DinD).

Для работы DinD в конфигурации пайплайна подключают специальный сервис. Это позволяет внутреннему контейнеру обращаться к Docker-демону для выполнения команд сборки.

На Схеме 1 показано, как происходит взаимодействие между компонентами во время выполнения задачи.

Практическая реализация пайплайна

Настроим файл .gitlab-ci.yml для автоматической сборки Python-приложения. Мы создадим образ и пометим его уникальным тегом, используя короткий хэш коммита ($CI_COMMIT_SHORT_SHA). Это обеспечит прослеживаемость: вы всегда будете знать, из какой версии кода собран конкретный образ.

Пример настройки стадии сборки с использованием DinD:

stages:
  - build

build_image:
  stage: build
  image: docker:24.0.5 
  services:
    - docker:24.0.5-dind 
  variables:
    DOCKER_HOST: tcp://docker:2375
    DOCKER_TLS_CERTDIR: ""
    IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
  script:
    - docker login -u $CI_REGISTRY_USER -p $CI_JOB_TOKEN $CI_REGISTRY
    - docker build -t $IMAGE_TAG .
    - docker push $IMAGE_TAG

В этом примере происходит сборка Docker-образа в CI, где каждый шаг логируется. Если docker build завершится с ошибкой (например, из-за опечатки в Dockerfile), пайплайн остановится, и вы сразу об этом узнаете.

Пример с ошибками в безопасности и тегировании:

# ПЛОХО: статические пароли и тег latest
script:
  - docker login -u my_admin -p P@ssw0rd123 # ОПАСНО: пароль в открытом виде
  - docker build -t my-app:latest . # ПЛОХО: тег latest перезаписывается, историю не отследить
  - docker push my-app:latest

Оптимизация и российская специфика

При работе с российскими облачными провайдерами (Yandex Cloud, VK Cloud) учитывайте доступность базовых образов. В корпоративных сетях часто настраивают зеркала (mirrors) для ускорения загрузки 🛰️

Задание на самопроверку:

  1. Возьмите Dockerfile вашего Python-проекта.
  2. Создайте в корне проекта файл .gitlab-ci.yml с блоком build, как в примере выше.
  3. Добавьте в секцию script команду docker images, чтобы увидеть список созданных слоев в логах пайплайна.
  4. После успешного запуска проверьте раздел Deploy -> Container Registry в GitLab — там должен появиться ваш первый автоматизированный образ 📦

Мы научились создавать готовые к работе образы. Но просто хранить их в реестре недостаточно. Чтобы превратить их в работающие сервисы, нужно научиться управлять конфигурацией серверов.

В следующей теме мы разберем Ansible — инструмент для автоматизации настройки инфраструктуры, куда мы будем развертывать наши контейнеры.

Понравился урок?

Сохраните прогресс и получите персональный курс по любой теме — без форм и паролей

Продолжить в Telegram