Run a self-hosted agent in Docker

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

Ez a cikk útmutatást nyújt az Azure Pipelines-ügynök Dockerben való futtatásához. Beállíthat egy saját üzemeltetésű ügynököt az Azure Pipelinesban, hogy a Windows Server Core-ban (Windows-gazdagépekhez) vagy Ubuntu-tárolóban (Linux-gazdagépekhez) fusson a Dockerrel. Ez akkor hasznos, ha külső vezénylésű ügynököket szeretne futtatni, például az Azure Container Instancest. Ebben a cikkben egy teljes tároló-példát mutat be, beleértve az ügynök önfrissítésének kezelését is.

A Windows és a Linux egyaránt támogatott tárológazdaként. A Windows-tárolóknak Windows vmImagerendszeren kell futniuk. Az ügynök Dockerben való futtatásához át kell adnia néhány környezeti változótdocker run, amelyek úgy konfigurálják az ügynököt, hogy csatlakozzon az Azure Pipelineshoz vagy az Azure DevOps Serverhez. Végül testre szabhatja a tárolót az igényeinek megfelelően. A feladatok és szkriptek attól függhetnek, hogy adott eszközök elérhetők-e a tárolóban PATH, és az Ön felelőssége annak biztosítása, hogy ezek az eszközök elérhetők legyenek.

Ehhez a funkcióhoz az ügynök 2.149-es vagy újabb verziója szükséges. Az Azure DevOps 2019 nem kompatibilis ügynökverzióval szállít. Ha azonban Docker-ügynököket szeretne futtatni, feltöltheti a megfelelő ügynökcsomagot az alkalmazásszintre .

Ablakok

A Hyper-V engedélyezése

A Hyper-V alapértelmezés szerint nincs engedélyezve Windows rendszeren. Ha elkülönítést szeretne biztosítani a tárolók között, engedélyeznie kell a Hyper-V-t. Ellenkező esetben a WindowsHoz készült Docker nem indul el.

Megjegyzés:

Engedélyeznie kell a virtualizálást a gépen. Ez általában alapértelmezés szerint engedélyezve van. Ha azonban a Hyper-V telepítése sikertelen, tekintse meg a rendszer dokumentációját a virtualizálás engedélyezéséhez.

A WindowsHoz készült Docker telepítése

Windows 10 használata esetén telepítheti a Docker Community Editiont. Windows Server 2016 esetén telepítse a Docker Enterprise kiadás.

A Docker váltása Windows-tárolók használatára

A WindowsHoz készült Docker alapértelmezés szerint Linux-tárolók használatára van konfigurálva. A Windows-tároló futtatásának engedélyezéséhez győződjön meg arról, hogy a Windows Docker a Windows démont futtatja.

A Dockerfile létrehozása és létrehozása

Ezután hozza létre a Dockerfile-t.

  1. Nyisson meg egy parancssort.

  2. Hozzon létre egy új könyvtárat:

    mkdir "C:\azp-agent-in-docker\"
    
  3. Nyissa meg ezt az új könyvtárat:

    cd "C:\azp-agent-in-docker\"
    
  4. Mentse a következő tartalmat a következő nevű C:\azp-agent-in-docker\azp-agent-windows.dockerfilefájlba:

    FROM mcr.microsoft.com/windows/servercore:ltsc2022
    
    WORKDIR /azp/
    
    COPY ./start.ps1 ./
    
    CMD powershell .\start.ps1
    
  5. Mentse a következő tartalmat a következőre 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. Futtassa a következő parancsot a könyvtáron belül:

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

    A végső kép címkézett azp-agent:windows.

A kép indítása

Most, hogy létrehozott egy lemezképet, futtathat egy tárolót. Ez telepíti az ügynök legújabb verzióját, konfigurálja és futtatja az ügynököt. A megadott Azure DevOps- vagy Azure DevOps Server-példány megadott ügynökkészletét ( Default alapértelmezés szerint az ügynökkészletet) célozza meg:

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

Hálózati problémák esetén előfordulhat, hogy meg kell adnia a --network paramétert.

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

Előfordulhat, hogy meg kell adnia --interactive és megjelölnie (vagy egyszerűen-it) azt, ha le szeretné állítani a tárolót, és el szeretné távolítani az ügynököt a következővelCtrl + C: .--tty

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

Ha minden folyamatfeladathoz friss ügynöktárolót szeretne, adja át a --once jelölőt a run parancsnak.

docker run < . . . > --once

--once A jelzővel érdemes lehet egy tárolóvezénylési rendszert használni, például a Kubernetes vagy az Azure Container Instances szolgáltatást, hogy a feladat befejezésekor elindítsa a tároló új példányát.

Az ügynök nevét, az ügynökkészletet és az ügynök munkakönyvtárát opcionális környezeti változók használatával szabályozhatja.

Linux

A Docker telepítése

A Linux-disztribúciótól függően telepítheti a Docker Community Editiont vagy a Docker Enterprise kiadás.

A Dockerfile létrehozása és létrehozása

Ezután hozza létre a Dockerfile-t.

  1. Nyisson meg egy terminált.

  2. Új könyvtár létrehozása (ajánlott):

    mkdir ~/azp-agent-in-docker/
    
  3. Nyissa meg ezt az új könyvtárat:

    cd ~/azp-agent-in-docker/
    
  4. Mentse a következő tartalmat a következőre ~/azp-agent-in-docker/azp-agent-linux.dockerfile:

    • Alpesi esetén:

      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" ]
      
    • Ubuntu 22.04 esetén:

      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" ]
      

    Bontsa ki a sort, ENV AGENT_ALLOW_RUNASROOT="true" és távolítsa el a agent felhasználó hozzáadását a sor előtt, ha gyökérként szeretné futtatni az ügynököt.

    Megjegyzés:

    A feladatok azoktól a végrehajtható műveletektől függhetnek, amelyeket a tárolónak meg kell adnia. A parancs futtatásához RUN apt install -y például hozzá kell adnia a zip csomagokat és unzipExtractFiles a csomagokat a ArchiveFiles parancshoz. Mivel ez egy Linux Ubuntu-rendszerkép az ügynök számára, igény szerint testre szabhatja a rendszerképet. Például: ha .NET-alkalmazásokat kell létrehoznia, kövesse a .NET SDK vagy a .NET futtatókörnyezet telepítése az Ubuntu-on című dokumentumot, és adja hozzá a rendszerképhez.

  5. Mentse a következő tartalmat a ~/azp-agent-in-docker/start.shunix stílusú (LF) sorvégződések használatára:

    #!/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 $!
    

    Megjegyzés:

    Egy tárolóvezénylési rendszert ( például Kubernetes vagy Azure Container Instances) is használnia kell a tároló új példányainak elindításához, amikor a munka befejeződik.

  6. Futtassa a következő parancsot a könyvtáron belül:

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

    A végső kép címkézett azp-agent:linux.

A kép indítása

Most, hogy létrehozott egy lemezképet, futtathat egy tárolót. Ez telepíti az ügynök legújabb verzióját, konfigurálja és futtatja az ügynököt. A megadott Azure DevOps- vagy Azure DevOps Server-példány megadott ügynökkészletét ( Default alapértelmezés szerint az ügynökkészletet) célozza meg:

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

Előfordulhat, hogy meg kell adnia --interactive és megjelölnie (vagy egyszerűen-it) azt, ha le szeretné állítani a tárolót, és el szeretné távolítani az ügynököt a következővelCtrl + C: .--tty

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

Ha minden folyamatfeladathoz friss ügynöktárolót szeretne, adja át a --once jelölőt a run parancsnak.

docker run < . . . > --once

--once A jelzővel érdemes lehet egy tárolóvezénylési rendszert használni, például a Kubernetes vagy az Azure Container Instances szolgáltatást, hogy a feladat befejezésekor elindítsa a tároló új példányát.

Az ügynök nevét, az ügynökkészletet és az ügynök munkakönyvtárát opcionális környezeti változók használatával szabályozhatja.

Környezeti változók

Környezeti változó Leírás
AZP_URL Az Azure DevOps vagy az Azure DevOps Server-példány URL-címe.
AZP_TOKEN Személyes hozzáférési jogkivonat (PAT) ügynökkészletekkel (olvasási, kezelési) hatókörrel, amelyet egy olyan felhasználó hozott létre, aki engedéllyel rendelkezik az ügynökök konfigurálására a következő helyenAZP_URL: .
AZP_AGENT_NAME Ügynök neve (alapértelmezett érték: a tároló állomásneve).
AZP_POOL Ügynökkészlet neve (alapértelmezett érték: Default).
AZP_WORK Munkahelyi könyvtár (alapértelmezett érték: _work).

Eszközök hozzáadása és a tároló testreszabása

Létrehozott egy alapszintű buildügynököt. Kibővítheti a Dockerfile-t további eszközökre és azok függőségeire, vagy létrehozhat saját tárolót úgy, hogy ezt alaprétegként használja. Csak győződjön meg arról, hogy a következők érintetlenek maradnak:

  • A start.sh szkriptet a Dockerfile hívja meg.
  • A start.sh szkript a Dockerfile utolsó parancsa.
  • Győződjön meg arról, hogy a származtatott tárolók nem távolítják el a Dockerfile által megadott függőségeket.

Docker használata Docker-tárolón belül

Ahhoz, hogy a Dockert egy Docker-tárolón belülről lehessen használni, csatlakoztatnia kell a Docker-szoftvercsatornát.

Figyelmeztetés

Ennek komoly biztonsági következményei vannak. A tárolóban lévő kód mostantól gyökérként futtatható a Docker-gazdagépen.

Ha biztos benne, hogy ezt meg szeretné tenni, tekintse meg a kötés csatlakoztatásának dokumentációját a Docker.com.

Az Azure Kubernetes Service-fürt használata

Figyelmeztetés

Vegye figyelembe, hogy a Docker-alapú feladatok nem fognak működni az AKS 1.19-ben vagy újabb verzióiban a Docker korlátozása miatt. A Dockert a Kubernetes 1.19-ben tárolóra cserélték, és a Docker-in-Docker elérhetetlenné vált.

Az Azure Kubernetes Service üzembe helyezése és konfigurálása

Kövesse a rövid útmutató lépéseit : Azure Kubernetes Service-fürt (AKS) üzembe helyezése az Azure Portal használatával. Ezt követően a PowerShell vagy a Shell-konzol használhatja a parancssort kubectl .

Az Azure Container Registry üzembe helyezése és konfigurálása

Kövesse a rövid útmutató lépéseit : Azure-tárolóregisztrációs adatbázis létrehozása az Azure Portal használatával. Ezt követően leküldheti és lekérheti a tárolókat az Azure Container Registryből.

Titkos kódok konfigurálása és replikakészlet üzembe helyezése

  1. Hozza létre a titkos kulcsokat az AKS-fürtön.

    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. Futtassa ezt a parancsot a tároló tárolóregisztrációs adatbázisba való leküldéséhez:

    docker push "<acr-server>/azp-agent:<tag>"
    
  3. Konfigurálja a Container Registry-integrációt a meglévő AKS-fürtökhöz.

    Megjegyzés:

    Ha több előfizetése van az Azure Portalon, először ezt a parancsot használva válasszon ki egy előfizetést

    az account set --subscription "<subscription id or subscription name>"
    
    az aks update -n "<myAKSCluster>" -g "<myResourceGroup>" --attach-acr "<acr-name>"
    
  4. Mentse a következő tartalmat a következőre ~/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
    

    Ez a Kubernetes YAML létrehoz egy replikakészletet és egy üzembe helyezést, amely replicas: 1 a fürtön futó számokat vagy ügynököket jelzi.

  5. Futtassa ezt a parancsot:

    kubectl apply -f ReplicationController.yml
    

Az ügynökök most futtatják az AKS-fürtöt.

Egyéni MTU-paraméter beállítása

Engedélyezze a tárolófeladatok által használt hálózatok MTU-értékének megadását (a k8s-fürt docker-in-docker-forgatókönyveiben hasznos).

Az MTU-érték beállításához be kell állítania a AGENT_DOCKER_MTU_VALUE környezeti változót, majd újra kell indítania a saját üzemeltetésű ügynököt. Az ügynök újraindításáról és az egyes ügynökök különböző környezeti változóinak beállításáról itt talál további információkat.

Ez lehetővé teszi egy hálózati paraméter beállítását a feladattárolóhoz. Ennek a parancsnak a használata hasonló a következő parancshoz a tárolóhálózat konfigurálása során:

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

Kötetek csatlakoztatása Docker-tárolón belüli Docker használatával

Ha egy Docker-tároló egy másik Docker-tárolón belül fut, mindkettő a gazdagép démonját használja, így az összes csatlakoztatási útvonal a gazdagépre hivatkozik, nem a tárolóra.

Ha például a gazdagépről a külső Docker-tárolóba szeretnénk csatlakoztatni az elérési utat, használhatjuk ezt a parancsot:

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

Ha a gazdagépről a belső Docker-tárolóba szeretnénk csatlakoztatni az útvonalat, használhatjuk ezt a parancsot:

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

De a külső tárolóból a belsőbe nem tudunk útvonalakat csatlakoztatni; ennek megkerüléséhez deklarálni kell egy ENV-változót:

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

Ezt követően elindíthatjuk a belső tárolót a külső tárolóból az alábbi paranccsal:

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

Common errors

Ha Windowst használ, és a következő hibaüzenet jelenik meg:

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

Telepítse a Git Basht a git-scm letöltésével és telepítésével.

Futtassa ezt a parancsot:

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

Try again. A hiba már nem jelenik meg.