Использование Azure Container Registry в Azure DevOps
В данной статье я хочу поделиться опытом использования Azure Container Registry на проектах с Azure DevOps. Реестр контейнеров используется для хранения образов Docker, Helm чартов и других артефактов OCI. Из дополнительных преимуществ ACR я бы выделил возможность сборки образов “на лету” (с помощью ACR task), возможность подключения сканера для поиска уязвимостей в образе и его зависимостях, а также георепликацию артефактов по выбранным ЦОДам (на момент написания статьи Azure предалагает 54 региона ).
CI для Docker с использованием Azure DevOps и ACR
Небольшое пояснения:
- Разработчик использует git, который развернут в Azure DevOps (Repos)
- Приложение будет упаковано в Docker образ со следующими условиями:
- Сборка будет производиться на агенте Azure DevOps (используется Pipeline);
- Образ, после сборки и сканирования на уязвимости, отправляется в Azure Container Regisry;
- Процесс повторяется автоматически (например, при обновлении файлов приложения или
Dockerfile
) или запускается в ручком режиме при необходимости.
Я буду использовать бесплатную версию Azure DevOps (на момент написания статьи 1800 минут работы агента в месяц, неограниченный git, 2 Гб для хранения артифактов и Azure Boards на 5 пользователей можно использовать бесплатно ).
Начнём с git
Для начала нужна организация в Azure DevOps и проект. Если ещё нет, то можно достаточно просто сделать это здесь.
Шаблон проекта не важен (я использую Agile). Если все проделано правильно, то на выходе должен получиться один дефолтный git репозиторий, используя git-клиент склонируем на локальную машину.
Сделаем ACR и дадим доступ к нему из Azure DevOps
Создать Azure Container Registry можно несколькими способами. Для данной статьи я использовал west europe
в качестве региона, сам ресурс создавал в базовой конфигурации (basic tier) для нашей цели этого достаточно.
- Сервер нашего хранилища (можно использовать в командах
docker
); - SKU (aka tier) - базовый. Также доступны
стандартный
ипремиум
конфигурации; - Можно сменить tier при необходимости.
У нас есть ресурс в Azure, теперь можно добавить его в Azure DevOps для использования во время сборки. Для этого находим Service Connections в Azure DevOps > Project Settings > Pipelines > Service Connections. Добавим новый с типом Docker Registry:
Я использовал Service Principal для подключения к моему ресурсу из AzDo Pipelines. После сохранения настроек в Azure AD в приложениях появится новое приложение. Исследуем его настройки, для этого через az cli
попробуем посмотреть список всех service connections:
PS C:\dev\azurefort> az devops service-endpoint list
Выделен сверху тот самый SPN, который имеет AcrPush
роль для нашего Azure Container Registry.
AcrPush
- позволяет отправить и получить образ (push & pull), чего вполне достаточно для нашей задачи.
Всё, service connection готов.
Dockerfile и контент
Будем использовать nginx
образ в качестве базового и добавим немного своего контента (html + картинка).
Вот тут git.
Немного пояснений:
FROM nginx
COPY src /usr/share/nginx/html
В src
лежит контент сайт (рядом с Dockerfile), который копируется в контейнер во время его сборки в путь /usr/share/nginx/html
. Сервер nginx с настройками по умолчанию загружает эту директорию и слушает порт 80.
Сборка приложения
Для сборки мы будем использовать Pipelines (синяя ракета! ). В Azure DevOps можно использовать классический визард (всё происходит через UI), YAML и расширенный YAML (Mutlistage). В данном примере я будут использовать последний, но сделаю короткий обзор первых двух.
Классический редактор
С ним достаточно просто начать, необходимо пройти небольшой визард, ответить на вопросы: где хранится код (например, можно использовать Bitbucket или свой собственный git) и далее в графическом интерфейсе выбрать какие конкретно таски (task) будут запускаться (на каком агенте) в пачке каких конкретно задач (job).
Отличный вариант конфигурации пайплайна, но хранить как код не получится, всё будет лежать где-то в БД Microsoft.. всё-таки yaml хочется, чтоб прям Инфраструктура-как-Код (IaC).
YAML и multistage
Эти два варианта очень похожи друг на друга (в multistage добавляется подолнительные indent’ы и появляется понятие stage
). Начинка задач (скоуп job) одинаковый. Ещё в multistage добавляется дополнительный тип задач (в дополнение к традиционным), который называется deployment.
Вернёмся к нашей поставленной задаче. Посмотрим на наш yaml:
trigger: none
stages:
- stage: build
pool:
vmImage: 'ubuntu-latest'
jobs:
- job: build
steps:
- task: Docker@2
inputs:
containerRegistry: 'azurefort'
repository: 'my-nginx'
command: 'buildAndPush'
Dockerfile: '**/Dockerfile'
У нас всего один stage
с одной job
и одной task
.
Лучше всего работать с этим файлов через редактор Pipelines, меньше будет опечаток и синтаксических ошибок. Рекомендую также использовать ассистент для задач.
Сохраним и запустим.
В результате сборки в реестре образов появился новый образ my-nginx
с нашим приложением и тэгом $(build.buildid)
. Рекомендую ознакомиться со встроенными переменными, они позволяет оптимизировать работу пайплайна, иметь меньше хардкода.
Несколько полезных команд для работы с ACR / Docker
- Подключиться к ACR:
# подключиться к реестру образов
az acr login -n <name>
Login Succeeded
# получить список доступных образов в реестре
az acr repository list -n <name> // список образов
# скачать образ my-nginx:2
docker pull <name>.azurecr.io/my-nginx:2
# запустить образ, слушать на ноде 8080, в контейнере - 80
# (tip: curl -v localhost:8080)
docker run -d -p 8080:80 <name>.azurecr.io/my-nginx:2
Список пополнятся!
Что дальше?
- Дальше можно автоматизировать сборку добавив
trigger: <branch>
. Допустим вы хотите собирать новый образ каждый раз когда вы делаетеpush
илиmerge
сmain
веткой; - Добавить Azure Key Vault для секретов, сертификатов итд;
- С помощью дополнительных
stages
можно деплоить приложение. Вот здесь расписывал как работать с docker-compose.
Удачи