Spuštění agenta v místním prostředí v Dockeru

Azure DevOps Services | Azure DevOps Server 2022 – Azure DevOps Server 2019

Tento článek obsahuje pokyny ke spuštění agenta Azure Pipelines v Dockeru. V Azure Pipelines můžete nastavit agenta v místním prostředí tak, aby běžel uvnitř jádra Windows Serveru (pro hostitele s Windows) nebo kontejneru Ubuntu (pro hostitele s Linuxem) pomocí Dockeru. To je užitečné, když chcete spouštět agenty s vnější orchestrací, jako je Azure Container Instances. V tomto článku si projdete kompletní příklad kontejneru, včetně samoobslužné aktualizace agenta.

Windows i Linux se podporují jako hostitelé kontejnerů. Kontejnery Windows by měly běžet ve Windows vmImage. Pokud chcete spustit agenta v Dockeru, předáte do docker runněho několik proměnných prostředí, které nakonfiguruje agenta pro připojení ke službě Azure Pipelines nebo Azure DevOps Serveru. Nakonec kontejner přizpůsobíte tak, aby vyhovoval vašim potřebám. Úlohy a skripty můžou záviset na dostupnosti konkrétních nástrojů v kontejneru PATHa je vaší zodpovědností zajistit, aby byly tyto nástroje k dispozici.

Tato funkce vyžaduje agenta verze 2.149 nebo novější. Azure DevOps 2019 se nedoručil s kompatibilní verzí agenta. Pokud ale chcete spustit agenty Dockeru, můžete do vrstvy aplikace nahrát správný balíček agenta.

Windows

Povolení Hyper-V

Ve Windows není ve výchozím nastavení povolená technologie Hyper-V. Pokud chcete zajistit izolaci mezi kontejnery, musíte povolit Technologii Hyper-V. Jinak se Docker pro Windows nespustí.

Poznámka:

Na počítači musíte povolit virtualizaci. Obvykle je povolená ve výchozím nastavení. Pokud se ale instalace Hyper-V nezdaří, projděte si dokumentaci k systému a zjistěte, jak povolit virtualizaci.

Instalace Dockeru pro Windows

Pokud používáte Windows 10, můžete nainstalovat Docker Community Edition. Pro Windows Server 2016 nainstalujte edice Enterprise Dockeru.

Přepnutí Dockeru na používání kontejnerů Windows

Ve výchozím nastavení je Docker pro Windows nakonfigurovaný tak, aby používal kontejnery Linuxu. Pokud chcete povolit spuštění kontejneru Windows, ověřte, že docker pro Windows používá proces démon Systému Windows.

Vytvoření a sestavení souboru Dockerfile

Dále vytvořte soubor Dockerfile.

  1. Otevřete příkazový řádek.

  2. Vytvořte nový adresář:

    mkdir "C:\azp-agent-in-docker\"
    
  3. Přejděte do tohoto nového adresáře:

    cd "C:\azp-agent-in-docker\"
    
  4. Uložte následující obsah do souboru s názvem 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
    
  5. Uložte následující obsah do 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})"
    }
    
  6. V tomto adresáři spusťte následující příkaz:

    docker build --tag "azp-agent:windows" --file "./azp-agent-windows.dockerfile" .
    

    Konečný obrázek je označen azp-agent:windows.

Spuštění obrázku

Teď, když jste vytvořili image, můžete spustit kontejner. Tím se nainstaluje nejnovější verze agenta, nakonfiguruje ji a spustí agenta. Cílí na zadaný fond agentů ( Default ve výchozím nastavení fond agentů) zadané instance Azure DevOps nebo Azure DevOps Serveru podle vašeho výběru:

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

Pokud narazíte na problémy se sítí, budete možná muset zadat --network parametr.

docker run --network "Default Switch" < . . . >

Pokud chcete kontejner zastavit a odebrat agenta,CCtrl + budete možná muset zadat --interactive a --tty označit příznakem (nebo jednoduše).-it

docker run --interactive --tty < . . . >

Pokud chcete nový kontejner agenta pro každou úlohu kanálu, předejte --once příznak příkazurun.

docker run < . . . > --once

--once Pomocí příznaku můžete chtít použít systém orchestrace kontejnerů, jako je Kubernetes nebo Azure Container Instances, ke spuštění nové kopie kontejneru po dokončení úlohy.

Název agenta, fond agentů a pracovní adresář agenta můžete řídit pomocí volitelných proměnných prostředí.

Linux

Instalace Dockeru

V závislosti na distribuci Linuxu můžete nainstalovat Docker Community Edition nebo Docker edice Enterprise.

Vytvoření a sestavení souboru Dockerfile

Dále vytvořte soubor Dockerfile.

  1. Otevřete terminál.

  2. Vytvořte nový adresář (doporučeno):

    mkdir ~/azp-agent-in-docker/
    
  3. Přejděte do tohoto nového adresáře:

    cd ~/azp-agent-in-docker/
    
  4. Uložte následující obsah do ~/azp-agent-in-docker/azp-agent-linux.dockerfile:

    • Pro Alpine:

      FROM alpine
      
      RUN apk update
      RUN apk upgrade
      RUN apk add bash curl git icu-libs jq
      
      ENV TARGETARCH="linux-musl-x64"
      
      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" ]
      
    • Pro Ubuntu 22.04:

      FROM ubuntu:22.04
      
      RUN apt update -y && apt upgrade -y && apt install curl git jq libicu70 -y
      
      # Also can be "linux-arm", "linux-arm64".
      ENV TARGETARCH="linux-x64"
      
      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" ]
      

    Odkomentujte ENV AGENT_ALLOW_RUNASROOT="true" řádek a odeberte přidání agent uživatele před tento řádek, pokud chcete spustit agenta jako kořen.

    Poznámka:

    Úlohy můžou záviset na spustitelných souborech, u které se očekává, že váš kontejner bude poskytovat. Pokud chcete například spouštět ArchiveFiles úlohy, musíte do RUN apt install -y příkazu přidat zip balíčky unzip a ExtractFiles balíčky. Vzhledem k tomu, že se jedná o image Ubuntu linuxu, kterou má agent používat, můžete image přizpůsobit podle potřeby. Například: Pokud potřebujete sestavit aplikace .NET, můžete postupovat podle dokumentu Instalace sady .NET SDK nebo modulu runtime .NET na Ubuntu a jeho přidání do image.

  5. Uložte následující obsah do ~/azp-agent-in-docker/start.sh, ujistěte se, že používáte konce řádků ve stylu 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 $!
    

    Poznámka:

    Pokud chcete spustit nové kopie kontejneru po dokončení práce, musíte také použít systém orchestrace kontejnerů, jako je Kubernetes nebo Azure Container Instances.

  6. V tomto adresáři spusťte následující příkaz:

    docker build --tag "azp-agent:linux" --file "./azp-agent-linux.dockerfile" .
    

    Konečný obrázek je označen azp-agent:linux.

Spuštění obrázku

Teď, když jste vytvořili image, můžete spustit kontejner. Tím se nainstaluje nejnovější verze agenta, nakonfiguruje ji a spustí agenta. Cílí na zadaný fond agentů ( Default ve výchozím nastavení fond agentů) zadané instance Azure DevOps nebo Azure DevOps Serveru podle vašeho výběru:

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

Pokud chcete kontejner zastavit a odebrat agenta,CCtrl + budete možná muset zadat --interactive a --tty označit příznakem (nebo jednoduše).-it

docker run --interactive --tty < . . . >

Pokud chcete nový kontejner agenta pro každou úlohu kanálu, předejte --once příznak příkazurun.

docker run < . . . > --once

--once Pomocí příznaku můžete chtít použít systém orchestrace kontejnerů, jako je Kubernetes nebo Azure Container Instances, ke spuštění nové kopie kontejneru po dokončení úlohy.

Název agenta, fond agentů a pracovní adresář agenta můžete řídit pomocí volitelných proměnných prostředí.

Proměnné prostředí

Proměnná prostředí Popis
AZP_URL Adresa URL instance Azure DevOps nebo Azure DevOps Serveru.
AZP_TOKEN Osobní přístupový token (PAT) s oborem fondů agentů (čtení, správa) vytvořeným uživatelem, který má oprávnění ke konfiguraci agentů, na adrese AZP_URL.
AZP_AGENT_NAME Název agenta (výchozí hodnota: název hostitele kontejneru).
AZP_POOL Název fondu agentů (výchozí hodnota: Default).
AZP_WORK Pracovní adresář (výchozí hodnota: _work).

Přidání nástrojů a přizpůsobení kontejneru

Vytvořili jste základního agenta sestavení. Soubor Dockerfile můžete rozšířit tak, aby zahrnoval další nástroje a jejich závislosti, nebo pomocí tohoto souboru vytvořit vlastní kontejner jako základní vrstvu. Stačí se ujistit, že následující položky zůstanou nedotčené:

  • Skript start.sh je volána souborem Dockerfile.
  • Skript start.sh je poslední příkaz v souboru Dockerfile.
  • Ujistěte se, že odvozené kontejnery neodeberou žádné závislosti uvedené v souboru Dockerfile.

Použití Dockeru v rámci kontejneru Dockeru

Pokud chcete použít Docker z kontejneru Dockeru, připojte soket Dockeru.

Upozornění

To má vážné bezpečnostní důsledky. Kód uvnitř kontejneru se teď může na hostiteli Dockeru spustit jako root.

Pokud si nejste jistí, že to chcete udělat, přečtěte si dokumentaci k připojení vazby na Docker.com.

Použití clusteru Azure Kubernetes Service

Upozornění

Vezměte prosím v úvahu, že všechny úlohy založené na Dockeru nebudou fungovat na AKS 1.19 nebo novější kvůli omezení Dockeru. Docker byl nahrazen kontejnerem v Kubernetes 1.19 a Docker-in-Docker začal být nedostupný.

Nasazení a konfigurace služby Azure Kubernetes Service

Postupujte podle kroků v rychlém startu: Nasazení clusteru Azure Kubernetes Service (AKS) pomocí webu Azure Portal. Potom může konzola PowerShellu nebo prostředí použít kubectl příkazový řádek.

Nasazení a konfigurace služby Azure Container Registry

Postupujte podle kroků v rychlém startu: Vytvoření registru kontejneru Azure pomocí webu Azure Portal. Potom můžete nasdílení a vyžádání kontejnerů ze služby Azure Container Registry.

Konfigurace tajných kódů a nasazení sady replik

  1. Vytvořte tajné kódy v clusteru 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
    
  2. Spuštěním tohoto příkazu odešlete kontejner do služby Container Registry:

    docker push "<acr-server>/azp-agent:<tag>"
    
  3. Nakonfigurujte integraci služby Container Registry pro existující clustery AKS.

    Poznámka:

    Pokud máte na webu Azure Portal více předplatných, nejprve pomocí tohoto příkazu vyberte předplatné.

    az account set --subscription "<subscription id or subscription name>"
    
    az aks update -n "<myAKSCluster>" -g "<myResourceGroup>" --attach-acr "<acr-name>"
    
  4. Uložte následující obsah do ~/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
    

    Tento YAML Kubernetes vytvoří sadu replik a nasazení, kde replicas: 1 označuje číslo nebo agenty spuštěné v clusteru.

  5. Spusťte tento příkaz:

    kubectl apply -f ReplicationController.yml
    

Teď budou vaši agenti spouštět cluster AKS.

Nastavení vlastního parametru MTU

Povolit zadání hodnoty MTU pro sítě používané úlohami kontejneru (užitečné pro scénáře docker-in-dockeru v clusteru k8s).

Abyste nastavili hodnotu MTU, musíte nastavit proměnnou prostředí AGENT_DOCKER_MTU_VALUE a poté restartovat agenta v místním prostředí. Další informace o restartování agenta najdete tady a o nastavení různých proměnných prostředí pro každého jednotlivého agenta zde.

To vám umožní nastavit parametr sítě pro kontejner úloh, použití tohoto příkazu se podobá použití dalšího příkazu při konfiguraci sítě kontejneru:

-o com.docker.network.driver.mtu=AGENT_DOCKER_MTU_VALUE

Připojení svazků pomocí Dockeru v rámci kontejneru Dockeru

Pokud se kontejner Dockeru spouští v jiném kontejneru Dockeru, oba používají proces démon hostitele, takže všechny cesty připojení odkazují na hostitele, nikoli kontejner.

Pokud například chceme připojit cestu z hostitele do vnějšího kontejneru Dockeru, můžeme použít tento příkaz:

docker run ... -v "<path-on-host>:<path-on-outer-container>" ...

A pokud chceme připojit cestu z hostitele do vnitřního kontejneru Dockeru, můžeme použít tento příkaz:

docker run ... -v "<path-on-host>:<path-on-inner-container>" ...

Ale nemůžeme připojit cesty z vnějšího kontejneru do vnitřního; abychom to obejít, musíme deklarovat proměnnou ENV:

docker run ... --env DIND_USER_HOME=$HOME ...

Potom můžeme vnitřní kontejner spustit z vnějšího kontejneru pomocí tohoto příkazu:

docker run ... -v "${DIND_USER_HOME}:<path-on-inner-container>" ...

Běžné chyby

Pokud používáte Windows a zobrazí se následující chyba:

standard_init_linux.go:178: exec user process caused "no such file or directory"

Nainstalujte Git Bash stažením a instalací git-scm.

Spusťte tento příkaz:

dos2unix ~/azp-agent-in-docker/Dockerfile
dos2unix ~/azp-agent-in-docker/start.sh
git add .
git commit -m "Fixed CR"
git push

Zkuste to ještě jednou. Už se vám chyba nezobrazí.