Como Executar um agente auto-hospedado no Docker
Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019
Este artigo fornece instruções para executar o agente do Azure Pipelines no Docker. Você pode configurar um agente auto-hospedado no Azure Pipelines para ser executado dentro de um Windows Server Core (para hosts do Windows) ou contêiner do Ubuntu (para hosts Linux) com o Docker. Isso é útil quando você quer executar agentes com orquestração externa, como Instâncias de Contêiner do Azure. Neste artigo, você verá um exemplo completo de contêiner, incluindo o tratamento de autoatendimento do agente.
O Windows e o Linux têm suporte como hosts de contêiner. Os contêineres do Windows devem ser executados em um Windows vmImage
.
Para executar seu agente no Docker, você passará algumas variáveis de ambiente para docker run
, o que configura o agente para se conectar ao Azure Pipelines ou Azure DevOps Server. Por fim, você personaliza o contêiner para atender às suas necessidades. Tarefas e scripts podem depender de ferramentas específicas estarem disponíveis no PATH
do contêiner, e é sua responsabilidade garantir que essas ferramentas estejam disponíveis.
Esse recurso requer a versão 2.149 ou posterior do agente. O Azure DevOps 2019 não foi fornecido com uma versão de agente compatível. No entanto, você pode carregar o pacote de agente correto na camada de aplicativo se quiser executar agentes do Docker.
Windows
Habilitar Hyper-V
O Hyper-V não está habilitado por padrão no Windows. Se você quiser fornecer isolamento entre contêineres, deverá habilitar o Hyper-V. Caso contrário, o Docker for Windows não será iniciado.
Observação
Você deve habilitar a virtualização em seu computador. Normalmente, ela é habilitada por padrão. No entanto, se a instalação do Hyper-V falhar, consulte a documentação do sistema para saber como habilitar a virtualização.
Instalar o Docker para Windows
Se você estiver usando Windows 10, poderá instalar o Docker Community Edition. Para Windows Server 2016, instale a Edição Enterprise do Docker.
Alternar o Docker para usar contêineres do Windows
Por padrão, o Docker for Windows é configurado para usar contêineres do Linux. Para permitir a execução do contêiner do Windows, confirme se o Docker for Windows está executando o daemon do Windows.
Criar e compilar o Dockerfile
Em seguida, crie o Dockerfile.
Abra um prompt de comando.
Criará um diretório:
mkdir "C:\azp-agent-in-docker\"
Vá para este novo diretório:
cd "C:\azp-agent-in-docker\"
Salve o seguinte conteúdo em um arquivo chamado
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
Salve o seguinte conteúdo em
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})" }
Execute o seguinte comando nesse diretório:
docker build --tag "azp-agent:windows" --file "./azp-agent-windows.dockerfile" .
A imagem final está marcada como
azp-agent:windows
.
Inicia a imagem
Agora que você criou uma imagem, você pode executar um contêiner. Isso instala a versão mais recente do agente, a configura e executa o agente. Ele tem como destino o pool de agentes (o pool de agentes Default
por padrão) de uma instância especificada do Azure DevOps ou Azure DevOps Server de sua escolha:
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
Talvez seja necessário especificar o parâmetro --network
se você tiver problemas de rede.
docker run --network "Default Switch" < . . . >
Talvez seja necessário especificar os sinalizadores --interactive
e --tty
(ou simplesmente-it
) se quiser parar o contêiner e remover o agente com Ctrl
+ C
.
docker run --interactive --tty < . . . >
Se você quiser um novo contêiner de agente para cada trabalho de pipeline, passe o sinalizador --once
para o comando run
.
docker run < . . . > --once
Com o sinalizador --once
, talvez você deseje usar um sistema de orquestração de contêineres, como Kubernetes ou Instâncias de Contêiner do Azure, para iniciar uma nova cópia do contêiner quando o trabalho for concluído.
Opcionalmente, você pode controlar o nome do agente, o pool de agentes e o diretório de trabalho do agente usando variáveis de ambiente opcionais.
Linux
Instalar o Docker
Dependendo da distribuição do Linux, você pode instalar o Docker Community Edition ou o Docker Edição Enterprise.
Criar e compilar o Dockerfile
Em seguida, crie o Dockerfile.
Abra um terminal.
Crie um novo diretório (recomendado):
mkdir ~/azp-agent-in-docker/
Vá para este novo diretório:
cd ~/azp-agent-in-docker/
Salve o seguinte conteúdo em
~/azp-agent-in-docker/azp-agent-linux.dockerfile
:Para o 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" ]
Para o 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" ]
Remova o comentário da linha
ENV AGENT_ALLOW_RUNASROOT="true"
e remova a adição do usuárioagent
antes dessa linha se quiser executar o agente como root.Observação
As tarefas podem depender de executáveis que seu contêiner deve fornecer. Por exemplo, você deve adicionar os pacotes
zip
eunzip
ao comandoRUN apt install -y
para executar as tarefasArchiveFiles
eExtractFiles
. Além disso, como essa é uma imagem do Ubuntu do Linux para o agente usar, você pode personalizar a imagem conforme necessário. Por exemplo: se você precisar criar aplicativos .NET, poderá seguir o documento Instalar o SDK do .NET ou o Runtime do .NET no Ubuntu e adicioná-lo à sua imagem.Salve o seguinte conteúdo em
~/azp-agent-in-docker/start.sh
, certificando-se de usar terminações de linha no estilo 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 $!
Observação
Você também deve usar um sistema de orquestração de contêineres, como Kubernetes ou Instâncias de Contêiner do Azure, para iniciar novas cópias do contêiner quando o trabalho for concluído.
Execute o seguinte comando nesse diretório:
docker build --tag "azp-agent:linux" --file "./azp-agent-linux.dockerfile" .
A imagem final está marcada como
azp-agent:linux
.
Inicia a imagem
Agora que você criou uma imagem, você pode executar um contêiner. Isso instala a versão mais recente do agente, a configura e executa o agente. Ele tem como destino o pool de agentes (o pool de agentes Default
por padrão) de uma instância especificada do Azure DevOps ou Azure DevOps Server de sua escolha:
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
Talvez seja necessário especificar os sinalizadores --interactive
e --tty
(ou simplesmente-it
) se quiser parar o contêiner e remover o agente com Ctrl
+ C
.
docker run --interactive --tty < . . . >
Se você quiser um novo contêiner de agente para cada trabalho de pipeline, passe o sinalizador --once
para o comando run
.
docker run < . . . > --once
Com o sinalizador --once
, talvez você deseje usar um sistema de orquestração de contêineres, como Kubernetes ou Instâncias de Contêiner do Azure, para iniciar uma nova cópia do contêiner quando o trabalho for concluído.
Opcionalmente, você pode controlar o nome do agente, o pool de agentes e o diretório de trabalho do agente usando variáveis de ambiente opcionais.
Variáveis de ambiente
Variável de ambiente | Descrição |
---|---|
AZP_URL | A URL da instância do Azure DevOps ou do Azure DevOps Server. |
AZP_TOKEN | Pat (Token de Acesso Pessoal) com escopo de Pools de Agentes (leitura, gerenciamento), criado por um usuário que tem permissão para configurar agentes, em AZP_URL . |
AZP_AGENT_NAME | Nome do agente (valor padrão: o nome do host do contêiner). |
AZP_POOL | Nome do pool de agentes (valor padrão: Default ). |
AZP_WORK | Diretório de trabalho (valor padrão: _work ). |
Adicionar ferramentas e personalizar o contêiner
Você criou um agente de build básico. Você pode estender o Dockerfile para incluir ferramentas adicionais e suas dependências ou criar seu próprio contêiner usando este como uma camada base. Apenas certifique-se de que os seguintes itens sejam deixados intocados:
- O script
start.sh
é chamado pelo Dockerfile. - O script
start.sh
é o último comando no Dockerfile. - Verifique se os contêineres derivados não removem nenhuma das dependências declaradas pelo Dockerfile.
Usar o Docker em um contêiner do Docker
Para usar o Docker de dentro de um contêiner do Docker, você pode montar o soquete do Docker.
Cuidado
Fazer isso tem sérias implicações de segurança. O código dentro do contêiner agora pode ser executado como raiz no host do Docker.
Se você tiver certeza de que deseja fazer isso, confira a documentação de montagem de associação no Docker.com.
Usar o cluster do Serviço de Kubernetes do Azure
Cuidado
Considere que todas as tarefas baseadas no Docker não funcionarão no AKS 1.19 ou posterior devido à restrição de Docker em Docker. O Docker foi substituído por contêiner no Kubernetes 1.19 e o Docker em Docker ficou indisponível.
Implantar e configurar o Serviço de Kubernetes do Azure
Siga as etapas em Início Rápido: implantar um cluster do AKS (Serviço de Kubernetes do Azure) usando o portal do Azure. Depois disso, o console do PowerShell ou do Shell poderá usar a linha de comando kubectl
.
Implantar e configurar o Registro de Contêiner do Azure
Siga as etapas no Início Rápido: Criar um registro de contêiner do Azure usando o portal do Azure. Depois disso, você pode efetuar push e pull de contêineres de Registro de Contêiner do Azure.
Configurar segredos e implantar um conjunto de réplicas
Crie os segredos no cluster do 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
Execute esse comando para enviar o contêiner por push para o Registro de Contêiner:
docker push "<acr-server>/azp-agent:<tag>"
Configurar a integração do Registro de Contêiner para clusters do AKS existentes.
Observação
Se você tiver várias assinaturas no Portal do Azure, use esse comando primeiro para selecionar uma assinatura
az account set --subscription "<subscription id or subscription name>"
az aks update -n "<myAKSCluster>" -g "<myResourceGroup>" --attach-acr "<acr-name>"
Salve o seguinte conteúdo em
~/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
Esse YAML do Kubernetes cria um conjunto de réplica e uma implantação, em
replicas: 1
que indica o número ou os agentes que estão em execução no cluster.Execute este comando:
kubectl apply -f ReplicationController.yml
Agora, seus agentes executarão o cluster do AKS.
Definir parâmetro MTU personalizado
Permitir a especificação do valor de MTU para redes usadas por trabalhos de contêiner (útil para cenários docker em docker no cluster do k8s).
Você precisa definir a variável de ambiente AGENT_DOCKER_MTU_VALUE para definir o valor de MTU e, em seguida, reiniciar o agente auto-hospedado. Você pode encontrar mais informações sobre a reinicialização do agente aqui e sobre como definir variáveis de ambiente diferentes para cada agente individual aqui.
Isso permite que você configure um parâmetro de rede para o contêiner de trabalho; o uso desse comando é semelhante ao uso do próximo comando enquanto a configuração de rede de contêiner:
-o com.docker.network.driver.mtu=AGENT_DOCKER_MTU_VALUE
Montar volumes usando o Docker em um contêiner do Docker
Se um contêiner do Docker for executado dentro de outro contêiner do Docker, ambos usarão o daemon do host, portanto, todos os caminhos de montagem referenciam o host, não o contêiner.
Por exemplo, se quisermos montar o caminho do host para o contêiner externo do Docker, podemos usar este comando:
docker run ... -v "<path-on-host>:<path-on-outer-container>" ...
E se quisermos montar o caminho do host para o contêiner interno do Docker, poderemos usar este comando:
docker run ... -v "<path-on-host>:<path-on-inner-container>" ...
Porém, não podemos montar caminhos do contêiner externo para o interno; para contornar isso, precisamos declarar uma variável ENV:
docker run ... --env DIND_USER_HOME=$HOME ...
Depois disso, podemos iniciar o contêiner interno do externo usando este comando:
docker run ... -v "${DIND_USER_HOME}:<path-on-inner-container>" ...
Erros comuns
Se você estiver usando o Windows e receber o seguinte erro:
standard_init_linux.go:178: exec user process caused "no such file or directory"
Instale o Git Bash baixando e instalando git-scm.
Execute este comando:
dos2unix ~/azp-agent-in-docker/Dockerfile
dos2unix ~/azp-agent-in-docker/start.sh
git add .
git commit -m "Fixed CR"
git push
Tente novamente. Você não recebe mais o erro.