Aracılığıyla paylaş


Docker'da şirket içinde barındırılan bir aracı çalıştırma

Azure DevOps Services | Azure DevOps Server 2022 - Azure DevOps Server 2019

Bu makalede, Azure Pipelines aracınızı Docker'da çalıştırma yönergeleri sağlanır. Azure Pipelines'da Docker ile bir Windows Server Core (Windows konakları için) veya Ubuntu kapsayıcısı (Linux konakları için) içinde çalışacak şekilde şirket içinde barındırılan bir aracı ayarlayabilirsiniz. Bu, Azure Container Instances gibi dış düzenleme ile aracıları çalıştırmak istediğinizde kullanışlıdır. Bu makalede, aracı kendi kendine güncelleştirmesini işleme de dahil olmak üzere eksiksiz bir kapsayıcı örneğini inceleyeceksiniz.

Hem Windows hem de Linux kapsayıcı konakları olarak desteklenir. Windows kapsayıcıları bir Windows vmImageüzerinde çalıştırılmalıdır. Aracınızı Docker'da çalıştırmak için aracıyı Azure Pipelines'a docker runveya Azure DevOps Server'a bağlanacak şekilde yapılandıran öğesine birkaç ortam değişkeni geçireceksiniz. Son olarak kapsayıcıyı gereksinimlerinize uyacak şekilde özelleştirebilirsiniz. Görevler ve betikler, kapsayıcının PATHüzerinde kullanılabilen belirli araçlara bağlı olabilir ve bu araçların kullanılabilir olduğundan emin olmak sizin sorumluluğunuzdadır.

Bu özellik için aracı sürümü 2.149 veya üzeri gerekir. Azure DevOps 2019 uyumlu bir aracı sürümüyle birlikte gelmedi. Ancak Docker aracılarını çalıştırmak istiyorsanız doğru aracı paketini uygulama katmanınıza yükleyebilirsiniz.

Windows

Hyper-V'yi etkinleştirme

Hyper-V, Windows'ta varsayılan olarak etkin değildir. Kapsayıcılar arasında yalıtım sağlamak istiyorsanız Hyper-V'yi etkinleştirmeniz gerekir. Aksi takdirde, Windows için Docker başlatılmaz.

Not

Makinenizde sanallaştırmayı etkinleştirmeniz gerekir. Genellikle varsayılan olarak etkindir. Ancak, Hyper-V yüklemesi başarısız olursa sanallaştırmayı etkinleştirme hakkında sistem belgelerinize bakın.

Windows için Docker'ı yükleme

Windows 10 kullanıyorsanız Docker Community Edition'ı yükleyebilirsiniz. Windows Server 2016 için Docker Enterprise Sürümü yükleyin.

Docker'ı Windows kapsayıcılarını kullanacak şekilde değiştirme

Varsayılan olarak, Windows için Docker Linux kapsayıcılarını kullanacak şekilde yapılandırılır. Windows kapsayıcısının çalıştırılmasına izin vermek için Windows için Docker'ın Windows daemon'unu çalıştırdığını onaylayın.

Dockerfile oluşturma ve oluşturma

Ardından Dockerfile'ı oluşturun.

  1. Komut istemi açın.

  2. Yeni dizin oluşturma:

    mkdir "C:\azp-agent-in-docker\"
    
  3. Şu yeni dizine gidin:

    cd "C:\azp-agent-in-docker\"
    
  4. Aşağıdaki içeriği adlı C:\azp-agent-in-docker\azp-agent-windows.dockerfilebir dosyaya kaydedin:

    FROM mcr.microsoft.com/windows/servercore:ltsc2022
    
    WORKDIR /azp/
    
    COPY ./start.ps1 ./
    
    CMD powershell .\start.ps1
    
  5. Aşağıdaki içeriği 'ye C:\azp-agent-in-docker\start.ps1kaydedin:

    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. Bu dizinde aşağıdaki komutu çalıştırın:

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

    Son görüntü etiketli azp-agent:windows.

Resmi başlatma

Artık bir görüntü oluşturduğunuza göre bir kapsayıcı çalıştırabilirsiniz. Bu, aracının en son sürümünü yükler, yapılandırılır ve aracıyı çalıştırır. Seçtiğiniz belirli bir Azure DevOps veya Azure DevOps Server örneğinin belirtilen aracı havuzunu ( Default varsayılan olarak aracı havuzu) hedefler:

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

Ağ sorunlarıyla karşılaşırsanız parametresini --network belirtmeniz gerekebilir.

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

Kapsayıcıyı durdurmak ve --tty aracısını ileC + Ctrl kaldırmak istiyorsanız ve bayrakları (veya basitçe-it) belirtmeniz --interactive gerekebilir.

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

Her işlem hattı işi için yeni bir aracı kapsayıcısı istiyorsanız bayrağını --once komutuna run geçirin.

docker run < . . . > --once

bayrağıyla, iş tamamlandığında kapsayıcının --once yeni bir kopyasını başlatmak için Kubernetes veya Azure Container Instances gibi bir kapsayıcı düzenleme sistemi kullanmak isteyebilirsiniz.

İsteğe bağlı ortam değişkenlerini kullanarak aracı adını, aracı havuzunu ve aracı iş dizinini denetleyebilirsiniz.

Linux

Docker'ı yükleme

Linux Dağıtımınıza bağlı olarak Docker Community Edition veya Docker Enterprise Sürümü yükleyebilirsiniz.

Dockerfile oluşturma ve oluşturma

Ardından Dockerfile'ı oluşturun.

  1. Bir terminal açın.

  2. Yeni dizin oluşturma (önerilen):

    mkdir ~/azp-agent-in-docker/
    
  3. Şu yeni dizine gidin:

    cd ~/azp-agent-in-docker/
    
  4. Aşağıdaki içeriği 'ye ~/azp-agent-in-docker/azp-agent-linux.dockerfilekaydedin:

    • Alpler için:

      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 için:

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

    Aracıyı kök olarak çalıştırmak istiyorsanız satırın ENV AGENT_ALLOW_RUNASROOT="true" açıklamasını kaldırın ve kullanıcıyı bu satırdan önce eklemeyi agent kaldırın.

    Not

    Görevler, kapsayıcınızın sağlaması beklenen yürütülebilir dosyalara bağlı olabilir. Örneğin, ve görevlerini çalıştırmak için RUN apt install -y ve unzip ExtractFiles paketlerini komutuna ArchiveFiles eklemeniz zip gerekir. Ayrıca, aracının kullanması için bir Linux Ubuntu görüntüsü olduğundan, görüntüyü istediğiniz gibi özelleştirebilirsiniz. Örneğin: .NET uygulamaları oluşturmanız gerekiyorsa Ubuntu'da .NET SDK'sını veya .NET Çalışma Zamanı'nı yükleme belgesini izleyebilir ve bunu görüntünüze ekleyebilirsiniz.

  5. Unix stili (LF) satır sonlarını kullandığınızdan emin olmak için aşağıdaki içeriği ~/azp-agent-in-docker/start.shöğesine kaydedin:

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

    Not

    Ayrıca, iş tamamlandığında kapsayıcının yeni kopyalarını başlatmak için Kubernetes veya Azure Container Instances gibi bir kapsayıcı düzenleme sistemi kullanmanız gerekir.

  6. Bu dizinde aşağıdaki komutu çalıştırın:

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

    Son görüntü etiketli azp-agent:linux.

Resmi başlatma

Artık bir görüntü oluşturduğunuza göre bir kapsayıcı çalıştırabilirsiniz. Bu, aracının en son sürümünü yükler, yapılandırılır ve aracıyı çalıştırır. Seçtiğiniz belirli bir Azure DevOps veya Azure DevOps Server örneğinin belirtilen aracı havuzunu ( Default varsayılan olarak aracı havuzu) hedefler:

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

Kapsayıcıyı durdurmak ve --tty aracısını ileC + Ctrl kaldırmak istiyorsanız ve bayrakları (veya basitçe-it) belirtmeniz --interactive gerekebilir.

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

Her işlem hattı işi için yeni bir aracı kapsayıcısı istiyorsanız bayrağını --once komutuna run geçirin.

docker run < . . . > --once

bayrağıyla, iş tamamlandığında kapsayıcının --once yeni bir kopyasını başlatmak için Kubernetes veya Azure Container Instances gibi bir kapsayıcı düzenleme sistemi kullanmak isteyebilirsiniz.

İsteğe bağlı ortam değişkenlerini kullanarak aracı adını, aracı havuzunu ve aracı iş dizinini denetleyebilirsiniz.

Ortam değişkenleri

Ortam değişkeni Açıklama
AZP_URL Azure DevOps veya Azure DevOps Server örneğinin URL'si.
AZP_TOKEN aracıları yapılandırma iznine sahip bir kullanıcı tarafından oluşturulan Aracı Havuzları (okuma, yönetme) kapsamına sahip Kişisel Erişim Belirteci (PAT) adresindeAZP_URL.
AZP_AGENT_NAME Aracı adı (varsayılan değer: kapsayıcı konak adı).
AZP_POOL Aracı havuzu adı (varsayılan değer: Default).
AZP_WORK İş dizini (varsayılan değer: _work).

Araç ekleme ve kapsayıcıyı özelleştirme

Temel bir derleme aracısı oluşturdunuz. Dockerfile'ı ek araçları ve bağımlılıklarını içerecek şekilde genişletebilir veya bunu temel katman olarak kullanarak kendi kapsayıcınızı oluşturabilirsiniz. Yalnızca aşağıdakilerin dokunulmadığından emin olun:

  • Betik start.sh Dockerfile tarafından çağrılır.
  • Betik start.sh , Dockerfile'daki son komutdur.
  • Türev kapsayıcıların Dockerfile tarafından belirtilen bağımlılıklardan hiçbirini kaldırmadığından emin olun.

Docker kapsayıcısı içinde Docker kullanma

Docker'ı bir Docker kapsayıcısının içinden kullanmak için Docker yuvasını bağlamanız gerekir.

Dikkat

Bunu yapmanın ciddi güvenlik etkileri vardır. Kapsayıcının içindeki kod artık Docker konağınızda kök olarak çalıştırılabilir.

Bunu yapmak istediğinizden eminseniz Docker.com bağlama belgelerine bakın.

Azure Kubernetes Service kümesini kullanma

Dikkat

Docker kısıtlaması nedeniyle docker tabanlı görevlerin AKS 1.19 veya sonraki sürümlerinde çalışmayacağını lütfen göz önünde bulundurun. Docker, Kubernetes 1.19'da kapsayıcılı olarak değiştirildi ve Docker-in-Docker kullanılamaz hale geldi.

Azure Kubernetes Service'i dağıtma ve yapılandırma

Hızlı Başlangıç: Azure portalını kullanarak Azure Kubernetes Service (AKS) kümesi dağıtma altındaki adımları izleyin. Bundan sonra PowerShell veya Kabuk konsolunuz komut satırını kullanabilir kubectl .

Azure Container Registry'yi dağıtma ve yapılandırma

Hızlı Başlangıç: Azure portalını kullanarak Azure kapsayıcı kayıt defteri oluşturma'daki adımları izleyin. Bundan sonra Azure Container Registry'den kapsayıcıları gönderip çekebilirsiniz.

Gizli dizileri yapılandırma ve çoğaltma kümesi dağıtma

  1. AKS kümesinde gizli dizileri oluşturun.

    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. Kapsayıcınızı Container Registry'ye göndermek için şu komutu çalıştırın:

    docker push "<acr-server>/azp-agent:<tag>"
    
  3. Mevcut AKS kümeleri için Container Registry tümleştirmesini yapılandırın.

    Not

    Azure Portal'da birden çok aboneliğiniz varsa lütfen önce bu komutu kullanarak bir abonelik seçin

    az account set --subscription "<subscription id or subscription name>"
    
    az aks update -n "<myAKSCluster>" -g "<myResourceGroup>" --attach-acr "<acr-name>"
    
  4. Aşağıdaki içeriği 'ye ~/AKS/ReplicationController.ymlkaydedin:

    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
    

    Bu Kubernetes YAML, replicas: 1 kümede çalışan aracıların sayısını veya aracılarını gösteren bir çoğaltma kümesi ve bir dağıtım oluşturur.

  5. Şu komutu çalıştırın:

    kubectl apply -f ReplicationController.yml
    

Artık aracılarınız AKS kümesini çalıştıracak.

Özel MTU parametresini ayarlama

Kapsayıcı işleri tarafından kullanılan ağlar için MTU değeri belirtmeye izin verin (k8s kümesindeki docker-in-docker senaryoları için kullanışlıdır).

MTU değerini ayarlamak için ortam değişkeni AGENT_DOCKER_MTU_VALUE ayarlamanız ve ardından şirket içinde barındırılan aracıyı yeniden başlatmanız gerekir. Aracı yeniden başlatma hakkında daha fazla bilgiye buradan ve her bir aracı için farklı ortam değişkenleri ayarlama hakkında burada bulabilirsiniz.

Bu, iş kapsayıcısı için bir ağ parametresi ayarlamanıza olanak tanır. Bu komutun kullanılması, kapsayıcı ağ yapılandırması sırasında sonraki komutun kullanımına benzer:

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

Docker kapsayıcısı içinde Docker kullanarak birimleri bağlama

Docker kapsayıcısı başka bir Docker kapsayıcısı içinde çalışıyorsa, her ikisi de konağın daemon'unu kullanır, bu nedenle tüm bağlama yolları kapsayıcıya değil konağa başvurur.

Örneğin, ana bilgisayardan dış Docker kapsayıcısına yol bağlamak istiyorsak şu komutu kullanabiliriz:

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

Ana bilgisayardan iç Docker kapsayıcısına yol bağlamak istiyorsak şu komutu kullanabiliriz:

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

Ancak dış kapsayıcıdaki yolları iç kapsayıcıya bağlayamıyoruz; bu sorunu çözmek için bir ENV değişkeni bildirmemiz gerekir:

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

Bundan sonra, şu komutu kullanarak iç kapsayıcıyı dış kapsayıcıdan başlatabiliriz:

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

Sık karşılaşılan hatalar

Windows kullanıyorsanız ve aşağıdaki hatayı alırsanız:

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

Git-scm dosyasını indirip yükleyerek Git Bash'i yükleyin.

Şu komutu çalıştırın:

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

Yeniden deneyin. Artık hatayı alamayacaksınız.