Запуск локального агента в Docker
Azure DevOps Services | Azure DevOps Server 2022 — Azure DevOps Server 2019
В этой статье приведены инструкции по запуску агента Azure Pipelines в Docker. Вы можете настроить автономный агент в Azure Pipelines для запуска в Windows Server Core (для узлов Windows) или контейнера Ubuntu (для узлов Linux) с помощью Docker. Это полезно, если вы хотите запускать агенты с внешним оркестрацией, например Экземпляры контейнеров Azure. В этой статье описан полный пример контейнера, включая самостоятельное обновление агента.
Windows и Linux поддерживаются как узлы контейнеров. Контейнеры Windows должны работать в Windows vmImage
.
Чтобы запустить агент в Docker, вы передайте несколько переменных docker run
среды, в которые агент настраивает подключение к Azure Pipelines или Azure DevOps Server. Наконец, вы настраиваете контейнер в соответствии с вашими потребностями. Задачи и скрипты могут зависеть от определенных средств, доступных в контейнере PATH
, и это ваша ответственность за обеспечение доступности этих средств.
Для этой функции требуется агент версии 2.149 или более поздней. Azure DevOps 2019 не было отправлено с совместимой версией агента. Однако вы можете отправить правильный пакет агента на уровень приложений , если вы хотите запустить агенты Docker.
Windows
Включение Hyper-V
Hyper-V по умолчанию не включен в Windows. Если требуется обеспечить изоляцию между контейнерами, необходимо включить Hyper-V. В противном случае Docker для Windows не запустится.
Примечание.
Необходимо включить виртуализацию на компьютере. Обычно он включен по умолчанию. Однако если установка Hyper-V завершается сбоем, обратитесь к системной документации по включению виртуализации.
Установка Docker для Windows
Если вы используете Windows 10, вы можете установить Docker Community Edition. Для Windows Server 2016 установите выпуск Enterprise Docker.
Переключение Docker на использование контейнеров Windows
По умолчанию Docker для Windows настроен на использование контейнеров Linux. Чтобы разрешить запуск контейнера Windows, убедитесь, что Docker для Windows работает под управлением управляющей программы Windows.
Создание и сборка Dockerfile
Затем создайте Dockerfile.
Откройте командную строку.
Создайте каталог:
mkdir "C:\azp-agent-in-docker\"
Перейдите к этому новому каталогу:
cd "C:\azp-agent-in-docker\"
Сохраните следующее содержимое в файл с именем
C:\azp-agent-in-docker\azp-agent-windows.dockerfile
:FROM mcr.microsoft.com/windows/servercore:ltsc2022 WORKDIR /azp/ COPY ./start.ps1 ./ CMD powershell .\start.ps1
Сохраните следующее содержимое
C:\azp-agent-in-docker\start.ps1
:function Print-Header ($header) { Write-Host "`n${header}`n" -ForegroundColor Cyan } if (-not (Test-Path Env:AZP_URL)) { Write-Error "error: missing AZP_URL environment variable" exit 1 } if (-not (Test-Path Env:AZP_TOKEN_FILE)) { if (-not (Test-Path Env:AZP_TOKEN)) { Write-Error "error: missing AZP_TOKEN environment variable" exit 1 } $Env:AZP_TOKEN_FILE = "\azp\.token" $Env:AZP_TOKEN | Out-File -FilePath $Env:AZP_TOKEN_FILE } Remove-Item Env:AZP_TOKEN if ((Test-Path Env:AZP_WORK) -and -not (Test-Path $Env:AZP_WORK)) { New-Item $Env:AZP_WORK -ItemType directory | Out-Null } New-Item "\azp\agent" -ItemType directory | Out-Null # Let the agent ignore the token env variables $Env:VSO_AGENT_IGNORE = "AZP_TOKEN,AZP_TOKEN_FILE" Set-Location agent Print-Header "1. Determining matching Azure Pipelines agent..." $base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$(Get-Content ${Env:AZP_TOKEN_FILE})")) $package = Invoke-RestMethod -Headers @{Authorization=("Basic $base64AuthInfo")} "$(${Env:AZP_URL})/_apis/distributedtask/packages/agent?platform=win-x64&`$top=1" $packageUrl = $package[0].Value.downloadUrl Write-Host $packageUrl Print-Header "2. Downloading and installing Azure Pipelines agent..." $wc = New-Object System.Net.WebClient $wc.DownloadFile($packageUrl, "$(Get-Location)\agent.zip") Expand-Archive -Path "agent.zip" -DestinationPath "\azp\agent" try { Print-Header "3. Configuring Azure Pipelines agent..." .\config.cmd --unattended ` --agent "$(if (Test-Path Env:AZP_AGENT_NAME) { ${Env:AZP_AGENT_NAME} } else { hostname })" ` --url "$(${Env:AZP_URL})" ` --auth PAT ` --token "$(Get-Content ${Env:AZP_TOKEN_FILE})" ` --pool "$(if (Test-Path Env:AZP_POOL) { ${Env:AZP_POOL} } else { 'Default' })" ` --work "$(if (Test-Path Env:AZP_WORK) { ${Env:AZP_WORK} } else { '_work' })" ` --replace Print-Header "4. Running Azure Pipelines agent..." .\run.cmd } finally { Print-Header "Cleanup. Removing Azure Pipelines agent..." .\config.cmd remove --unattended ` --auth PAT ` --token "$(Get-Content ${Env:AZP_TOKEN_FILE})" }
Выполните следующую команду в этом каталоге:
docker build --tag "azp-agent:windows" --file "./azp-agent-windows.dockerfile" .
Окончательный образ помечен.
azp-agent:windows
Запуск образа
Теперь, когда вы создали образ, можно запустить контейнер. Это устанавливает последнюю версию агента, настраивает его и запускает агент. Он предназначен для указанного пула агентов ( Default
пул агентов по умолчанию) указанного экземпляра Azure DevOps или Azure DevOps Server по своему усмотрению:
docker run -e AZP_URL="<Azure DevOps instance>" -e AZP_TOKEN="<Personal Access Token>" -e AZP_POOL="<Agent Pool Name>" -e AZP_AGENT_NAME="Docker Agent - Windows" --name "azp-agent-windows" azp-agent:windows
При возникновении проблем с сетью --network
может потребоваться указать параметр.
docker run --network "Default Switch" < . . . >
Возможно, потребуется указать --interactive
и флаги (или просто-it
), если вы хотите остановить контейнер и удалить агент.Ctrl
+ C
--tty
docker run --interactive --tty < . . . >
Если требуется новый контейнер агента для каждого задания конвейера, передайте --once
флаг в run
команду.
docker run < . . . > --once
--once
С помощью флага может потребоваться использовать систему оркестрации контейнеров, например Kubernetes или Экземпляры контейнеров Azure, чтобы запустить новую копию контейнера после завершения задания.
Вы можете управлять именем агента, пулом агентов и рабочим каталогом агента с помощью необязательных переменных среды.
Linux
Установите Docker.
В зависимости от дистрибутива Linux можно установить Docker Community Edition или Docker выпуск Enterprise.
Создание и сборка Dockerfile
Затем создайте Dockerfile.
Откройте окно терминала.
Создайте каталог (рекомендуется):
mkdir ~/azp-agent-in-docker/
Перейдите к этому новому каталогу:
cd ~/azp-agent-in-docker/
Сохраните следующее содержимое
~/azp-agent-in-docker/azp-agent-linux.dockerfile
:Для Alpine:
FROM alpine ENV TARGETARCH="linux-musl-x64" # Another option: # FROM arm64v8/alpine # ENV TARGETARCH="linux-musl-arm64" RUN apk update RUN apk upgrade RUN apk add bash curl git icu-libs jq WORKDIR /azp/ COPY ./start.sh ./ RUN chmod +x ./start.sh RUN adduser -D agent RUN chown agent ./ USER agent # Another option is to run the agent as root. # ENV AGENT_ALLOW_RUNASROOT="true" ENTRYPOINT [ "./start.sh" ]
Для Ubuntu 22.04:
FROM ubuntu:22.04 ENV TARGETARCH="linux-x64" # Also can be "linux-arm", "linux-arm64". RUN apt update RUN apt upgrade -y RUN apt install -y curl git jq libicu70 WORKDIR /azp/ COPY ./start.sh ./ RUN chmod +x ./start.sh # Create agent user and set up home directory RUN useradd -m -d /home/agent agent RUN chown -R agent:agent /azp /home/agent USER agent # Another option is to run the agent as root. # ENV AGENT_ALLOW_RUNASROOT="true" ENTRYPOINT [ "./start.sh" ]
Раскомментируйте
ENV AGENT_ALLOW_RUNASROOT="true"
строку и удалите добавлениеagent
пользователя перед этой строкой, если вы хотите запустить агент в качестве корневого каталога.Примечание.
Задачи могут зависеть от исполняемых файлов, предоставляемых контейнером. Например, необходимо добавить
zip
в команду иunzip
пакетыRUN apt install -y
, чтобы выполнитьArchiveFiles
задачи иExtractFiles
задачи. Кроме того, так как это образ Ubuntu linux для используемого агента, вы можете настроить образ по мере необходимости. Например, если вам нужно создать приложения .NET, вы можете выполнить установку пакета SDK для .NET или среды выполнения .NET в Ubuntu и добавить его в образ.Сохраните следующее содержимое
~/azp-agent-in-docker/start.sh
, чтобы убедиться, что используется конец строки стиле Unix( LF):#!/bin/bash set -e if [ -z "${AZP_URL}" ]; then echo 1>&2 "error: missing AZP_URL environment variable" exit 1 fi if [ -z "${AZP_TOKEN_FILE}" ]; then if [ -z "${AZP_TOKEN}" ]; then echo 1>&2 "error: missing AZP_TOKEN environment variable" exit 1 fi AZP_TOKEN_FILE="/azp/.token" echo -n "${AZP_TOKEN}" > "${AZP_TOKEN_FILE}" fi unset AZP_TOKEN if [ -n "${AZP_WORK}" ]; then mkdir -p "${AZP_WORK}" fi cleanup() { trap "" EXIT if [ -e ./config.sh ]; then print_header "Cleanup. Removing Azure Pipelines agent..." # If the agent has some running jobs, the configuration removal process will fail. # So, give it some time to finish the job. while true; do ./config.sh remove --unattended --auth "PAT" --token $(cat "${AZP_TOKEN_FILE}") && break echo "Retrying in 30 seconds..." sleep 30 done fi } print_header() { lightcyan="\033[1;36m" nocolor="\033[0m" echo -e "\n${lightcyan}$1${nocolor}\n" } # Let the agent ignore the token env variables export VSO_AGENT_IGNORE="AZP_TOKEN,AZP_TOKEN_FILE" print_header "1. Determining matching Azure Pipelines agent..." AZP_AGENT_PACKAGES=$(curl -LsS \ -u user:$(cat "${AZP_TOKEN_FILE}") \ -H "Accept:application/json" \ "${AZP_URL}/_apis/distributedtask/packages/agent?platform=${TARGETARCH}&top=1") AZP_AGENT_PACKAGE_LATEST_URL=$(echo "${AZP_AGENT_PACKAGES}" | jq -r ".value[0].downloadUrl") if [ -z "${AZP_AGENT_PACKAGE_LATEST_URL}" -o "${AZP_AGENT_PACKAGE_LATEST_URL}" == "null" ]; then echo 1>&2 "error: could not determine a matching Azure Pipelines agent" echo 1>&2 "check that account "${AZP_URL}" is correct and the token is valid for that account" exit 1 fi print_header "2. Downloading and extracting Azure Pipelines agent..." curl -LsS "${AZP_AGENT_PACKAGE_LATEST_URL}" | tar -xz & wait $! source ./env.sh trap "cleanup; exit 0" EXIT trap "cleanup; exit 130" INT trap "cleanup; exit 143" TERM print_header "3. Configuring Azure Pipelines agent..." ./config.sh --unattended \ --agent "${AZP_AGENT_NAME:-$(hostname)}" \ --url "${AZP_URL}" \ --auth "PAT" \ --token $(cat "${AZP_TOKEN_FILE}") \ --pool "${AZP_POOL:-Default}" \ --work "${AZP_WORK:-_work}" \ --replace \ --acceptTeeEula & wait $! print_header "4. Running Azure Pipelines agent..." chmod +x ./run.sh # To be aware of TERM and INT signals call ./run.sh # Running it with the --once flag at the end will shut down the agent after the build is executed ./run.sh "$@" & wait $!
Примечание.
Кроме того, необходимо использовать систему оркестрации контейнеров, например Kubernetes или Экземпляры контейнеров Azure, чтобы начать новые копии контейнера после завершения работы.
Выполните следующую команду в этом каталоге:
docker build --tag "azp-agent:linux" --file "./azp-agent-linux.dockerfile" .
Окончательный образ помечен.
azp-agent:linux
Запуск образа
Теперь, когда вы создали образ, можно запустить контейнер. Это устанавливает последнюю версию агента, настраивает его и запускает агент. Он предназначен для указанного пула агентов ( Default
пул агентов по умолчанию) указанного экземпляра Azure DevOps или Azure DevOps Server по своему усмотрению:
docker run -e AZP_URL="<Azure DevOps instance>" -e AZP_TOKEN="<Personal Access Token>" -e AZP_POOL="<Agent Pool Name>" -e AZP_AGENT_NAME="Docker Agent - Linux" --name "azp-agent-linux" azp-agent:linux
Возможно, потребуется указать --interactive
и флаги (или просто-it
), если вы хотите остановить контейнер и удалить агент.Ctrl
+ C
--tty
docker run --interactive --tty < . . . >
Если требуется новый контейнер агента для каждого задания конвейера, передайте --once
флаг в run
команду.
docker run < . . . > --once
--once
С помощью флага может потребоваться использовать систему оркестрации контейнеров, например Kubernetes или Экземпляры контейнеров Azure, чтобы запустить новую копию контейнера после завершения задания.
Вы можете управлять именем агента, пулом агентов и рабочим каталогом агента с помощью необязательных переменных среды.
Переменные среды
Переменная среды | Description |
---|---|
AZP_URL | URL-адрес экземпляра Azure DevOps или Azure DevOps Server. |
AZP_TOKEN | Личный маркер доступа (PAT) с областью "Пулы агентов" (чтение, управление), созданная пользователем, у которого есть разрешение на настройку агентов.AZP_URL |
AZP_AGENT_NAME | Имя агента (значение по умолчанию: имя узла контейнера). |
AZP_POOL | Имя пула агентов (значение по умолчанию: Default ). |
AZP_WORK | Рабочий каталог (значение по умолчанию: _work ). |
Добавление средств и настройка контейнера
Вы создали базовый агент сборки. Вы можете расширить Dockerfile, чтобы включить дополнительные средства и их зависимости, или создать собственный контейнер с помощью этого файла в качестве базового слоя. Просто убедитесь, что указанные ниже элементы остаются неуправляемыми:
- Скрипт
start.sh
вызывается Dockerfile. - Скрипт
start.sh
— это последняя команда в Dockerfile. - Убедитесь, что производные контейнеры не удаляют ни одного из зависимостей, указанных в Dockerfile.
Использование Docker в контейнере Docker
Чтобы использовать Docker из контейнера Docker, необходимо привязать сокет Docker.
Внимание
Это имеет серьезные последствия для безопасности. Теперь код внутри контейнера может выполняться в качестве корневого каталога на узле Docker.
Если вы уверены, что хотите сделать это, см . документацию по подключению привязки на Docker.com.
Использование кластера Служба Azure Kubernetes
Внимание
Обратите внимание, что любые задачи на основе docker не будут работать в AKS 1.19 или более поздней версии из-за docker в ограничении Docker. Docker был заменен контейнером в Kubernetes 1.19, и Docker-in-Docker стал недоступным.
Развертывание и настройка Служба Azure Kubernetes
Выполните действия, описанные в кратком руководстве. Развертывание кластера Служба Azure Kubernetes (AKS) с помощью портал Azure. После этого консоль PowerShell или Shell может использовать командную kubectl
строку.
Развертывание и настройка Реестр контейнеров Azure
Выполните действия, описанные в разделе Краткое руководство. Создание реестра контейнеров Azure с помощью портала Azure. После этого можно отправить и извлечь контейнеры из Реестр контейнеров Azure.
Настройка секретов и развертывание набора реплик
Создайте секреты в кластере AKS.
kubectl create secret generic azdevops \ --from-literal=AZP_URL=https://dev.azure.com/yourOrg \ --from-literal=AZP_TOKEN=YourPAT \ --from-literal=AZP_POOL=NameOfYourPool
Выполните следующую команду, чтобы отправить контейнер в реестр контейнеров:
docker push "<acr-server>/azp-agent:<tag>"
Настройте интеграцию реестра контейнеров для существующих кластеров AKS.
Примечание.
Если на портале Azure несколько подписок, сначала используйте эту команду, чтобы выбрать подписку.
az account set --subscription "<subscription id or subscription name>"
az aks update -n "<myAKSCluster>" -g "<myResourceGroup>" --attach-acr "<acr-name>"
Сохраните следующее содержимое
~/AKS/ReplicationController.yml
:apiVersion: apps/v1 kind: Deployment metadata: name: azdevops-deployment labels: app: azdevops-agent spec: replicas: 1 # here is the configuration for the actual agent always running selector: matchLabels: app: azdevops-agent template: metadata: labels: app: azdevops-agent spec: containers: - name: kubepodcreation image: <acr-server>/azp-agent:<tag> env: - name: AZP_URL valueFrom: secretKeyRef: name: azdevops key: AZP_URL - name: AZP_TOKEN valueFrom: secretKeyRef: name: azdevops key: AZP_TOKEN - name: AZP_POOL valueFrom: secretKeyRef: name: azdevops key: AZP_POOL volumeMounts: - mountPath: /var/run/docker.sock name: docker-volume volumes: - name: docker-volume hostPath: path: /var/run/docker.sock
Этот YAML Kubernetes создает набор реплик и развертывание, где
replicas: 1
указывается число или агенты, работающие в кластере.Выполните следующую команду:
kubectl apply -f ReplicationController.yml
Теперь агенты будут запускать кластер AKS.
Настройка настраиваемого параметра MTU
Разрешить указание значения MTU для сетей, используемых заданиями контейнеров (полезно для сценариев docker в docker в кластере k8s).
Необходимо задать переменную среды AGENT_DOCKER_MTU_VALUE, чтобы задать значение MTU, а затем перезапустить локальный агент. Дополнительные сведения о перезапуске агента см. здесь и о настройке различных переменных среды для каждого отдельного агента здесь.
Это позволяет настроить сетевой параметр для контейнера заданий, использование этой команды аналогично использованию следующей команды при настройке сети контейнеров:
-o com.docker.network.driver.mtu=AGENT_DOCKER_MTU_VALUE
Подключение томов с помощью Docker в контейнере Docker
Если контейнер Docker выполняется внутри другого контейнера Docker, они оба используют управляющей программы узла, поэтому все пути подключения ссылаются на узел, а не контейнер.
Например, если мы хотим подключить путь от узла к внешнему контейнеру Docker, мы можем использовать следующую команду:
docker run ... -v "<path-on-host>:<path-on-outer-container>" ...
И если мы хотим подключить путь от узла к внутреннему контейнеру Docker, мы можем использовать следующую команду:
docker run ... -v "<path-on-host>:<path-on-inner-container>" ...
Но мы не можем подключить пути из внешнего контейнера в внутренний; чтобы обойти это, необходимо объявить переменную ENV:
docker run ... --env DIND_USER_HOME=$HOME ...
После этого можно запустить внутренний контейнер из внешнего контейнера с помощью следующей команды:
docker run ... -v "${DIND_USER_HOME}:<path-on-inner-container>" ...
Распространенные ошибки
Если вы используете Windows, и вы получите следующую ошибку:
standard_init_linux.go:178: exec user process caused "no such file or directory"
Установите Git Bash, скачав и установив git-scm.
Выполните следующую команду:
dos2unix ~/azp-agent-in-docker/Dockerfile
dos2unix ~/azp-agent-in-docker/start.sh
git add .
git commit -m "Fixed CR"
git push
Повторите попытку. Вы больше не получите ошибку.