Freigeben über


Containeraufträge in YAML-Pipelines

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

In diesem Artikel werden Containeraufträge in Azure Pipelines erläutert.

Standardmäßig werden Azure Pipelines-Aufträge direkt auf den Hostcomputern ausgeführt, auf denen der Agent installiert ist. Gehostete Agent-Aufträge sind praktisch, erfordern wenig Anfängliche Einrichtung und Infrastruktur, um zu warten, und eignen sich gut für grundlegende Projekte.

Wenn Sie mehr Kontrolle über den Aufgabenkontext wünschen, können Sie Aufträge in Containern definieren und ausführen. Container sind eine einfache Abstraktion über das Hostbetriebssystem, das eine Isolation vom Host bereitstellt. Wenn Sie Aufträge in Containern ausführen, können Sie die genauen Versionen von Betriebssystemen, Tools und Abhängigkeiten auswählen, die Ihr Build benötigt.

Linux- und Windows-Agents können Pipelineaufträge direkt auf dem Host oder in Containern ausführen. Containeraufträge sind unter macOS nicht verfügbar.

Bei einem Containerauftrag ruft der Agent zuerst den Container ab und startet den Container. Anschließend wird jeder Schritt des Auftrags innerhalb des Containers ausgeführt.

Wenn Sie eine differenzierte Steuerung auf der ebene der einzelnen Buildschritte benötigen, können Sie mit Schrittzielen einen Container oder Host für jeden Schritt auswählen.

Voraussetzungen und Einschränkungen

Die folgenden Anforderungen und Einschränkungen gelten für Azure Pipelines-Agenthosts oder -Container.

Agenthosts

  • Nur windows-*- und ubuntu-*-Images unterstützen das Ausführen von Containern. Die macos-* Images unterstützen das Ausführen von Containern nicht.
  • Zum Ausführen von Containern müssen Windows- und Linux-Agenthosts Docker installiert haben und über die Berechtigung zum Zugriff auf den Docker-Daemon verfügen.
  • Container werden nicht unterstützt, wenn der Agent bereits in einem Container ausgeführt wird. Geschachtelte Container sind nicht möglich.

Container

Linux-basierte Container haben die folgenden Anforderungen. Problemumgehungen finden Sie unter Nonglibc-basierte Container.

  • Bash installiert
  • GNU C Library (glibc)-basiert
  • Ohne ENTRYPOINT
  • Bereitstellen von USER Zugriff auf groupadd und anderen privilegierten Befehlen ohne Verwendung sudo
  • Kann Node.js ausführen, den der Agent bereitstellt

    Hinweis

    Node.js muss für Linux-Container auf Windows-Hosts vorinstalliert sein.

Einige entfernte Container, die auf Docker Hub verfügbar sind, insbesondere Container, die auf Alpine Linux basieren, erfüllen diese Anforderungen nicht. Container mit einer ENTRYPOINT Funktion funktionieren möglicherweise nicht, da Azure-Pipelines docker create ausgeführt werden und docker exec davon ausgehen, dass der Container immer ausgeführt wird.

Beispiele für einen einzelnen Auftrag

In den folgenden Beispielen wird ein Windows- oder Linux-Container für einen einzelnen Auftrag definiert.

Im folgenden einfachen Beispiel wird ein Linux-Container definiert:

pool:
  vmImage: 'ubuntu-latest'

container: ubuntu:18.04

steps:
- script: printenv

Im vorherigen Beispiel wird dem System mitgeteilt, das ubuntu vom Docker Hub markierte 18.04 Image abzurufen und dann den Container zu starten. Der printenv Befehl wird innerhalb des ubuntu:18.04 Containers ausgeführt.

Mehrere Aufträge

Sie können Container verwenden, um denselben Schritt in mehreren Aufträgen auszuführen. Im folgenden Beispiel wird derselbe Schritt in mehreren Versionen von Ubuntu Linux ausgeführt. Sie müssen das jobs Schlüsselwort nicht erwähnen, da nur ein einzelner Auftrag definiert ist.

pool:
  vmImage: 'ubuntu-latest'

strategy:
  matrix:
    ubuntu16:
      containerImage: ubuntu:16.04
    ubuntu18:
      containerImage: ubuntu:18.04
    ubuntu20:
      containerImage: ubuntu:20.04

container: $[ variables['containerImage'] ]

steps:
- script: printenv

Mehrere Aufträge mit Agentpools auf einem einzelnen Agenthost

Ein Containerauftrag verwendet die Docker-Konfigurationsdatei des zugrunde liegenden Host-Agents für die Imageregistrierungsautorisierung. Diese Datei meldet sich am Ende der Docker-Registrierungscontainerinitialisierung ab. Registrierungsimage-Pulls für nachfolgende Containeraufträge werden möglicherweise verweigert unauthorized authentication , da ein anderer Auftrag, der parallel ausgeführt wird, bereits die Docker-Konfigurationsdatei abgemeldet hat.

Die Lösung besteht darin, eine Docker-Umgebungsvariable DOCKER_CONFIG festzulegen, die für jeden Agentpool spezifisch ist, der auf dem gehosteten Agent ausgeführt wird. Exportieren Sie das skript im DOCKER_CONFIG runsvc.sh jedes Agentpools wie folgt:

export DOCKER_CONFIG=./.docker

Startoptionen

Sie können angeben options , dass der Containerstart gesteuert werden soll, wie im folgenden Beispiel gezeigt:

container:
  image: ubuntu:18.04
  options: --hostname container-test --ip 192.168.0.1

steps:
- script: echo hello

Beim Ausführen docker create --help erhalten Sie die Liste der Optionen, die Sie an den Docker-Aufruf übergeben können. Es ist nicht sicher, dass alle diese Optionen mit Azure DevOps funktionieren. Überprüfen Sie zuerst, ob Sie eine container Eigenschaft verwenden können, um dasselbe Ziel zu erreichen.

Weitere Informationen finden Sie in der Docker Create-Befehlsreferenz und der Definition "resources.containers.container" in der Azure DevOps YAML-Schemareferenz.

Definition wiederverwendbarer Container

Im folgenden Beispiel werden die Container im resources Abschnitt definiert und anschließend anhand ihrer zugewiesenen Aliase darauf verwiesen. Das jobs Schlüsselwort wird explizit zur Übersichtlichkeit aufgeführt.

resources:
  containers:
  - container: u16
    image: ubuntu:16.04

  - container: u18
    image: ubuntu:18.04

  - container: u20
    image: ubuntu:20.04

jobs:
- job: RunInContainer
  pool:
    vmImage: 'ubuntu-latest'

  strategy:
    matrix:
      ubuntu16:
        containerResource: u16
      ubuntu18:
        containerResource: u18
      ubuntu20:
        containerResource: u20

  container: $[ variables['containerResource'] ]

  steps:
  - script: printenv

Dienstendpunkte

Sie können Container in anderen Registrierungen als öffentlichem Docker Hub hosten. Um ein Image in der Azure Container Registry oder einer anderen privaten Containerregistrierung zu hosten, einschließlich einer privaten Docker Hub-Registrierung, fügen Sie eine Dienstverbindung für den Zugriff auf die Registrierung hinzu. Anschließend können Sie in der Containerdefinition auf den Endpunkt verweisen.

Private Docker Hub-Verbindung:

container:
  image: registry:ubuntu1804
  endpoint: private_dockerhub_connection

Azure Container Registry-Verbindung:

container:
  image: myprivate.azurecr.io/windowsservercore:1803
  endpoint: my_acr_connection

Hinweis

Azure Pipelines können keine Dienstverbindung für Amazon Elastic Container Registry (ECR) einrichten, da Amazon ECR andere Clienttools benötigt, um AWS-Anmeldeinformationen in etwas zu konvertieren, das Docker zur Authentifizierung verwenden kann.

Nichtglibc-basierte Container

Der Azure Pipelines-Agent stellt eine Kopie von Node.js bereit, die zum Ausführen von Aufgaben und Skripts erforderlich ist. Navigieren Sie zu Von Microsoft gehostete Agents, im die Version von Node.js für einen gehosteten Agent zu ermitteln.

Die Version von Node.js kompiliert mit der C-Laufzeit, die in der gehosteten Cloud verwendet wird, in der Regel glibc. Einige Linux-Varianten verwenden andere C-Runtimes. Alpine Linux verwendet beispielsweise musl.

Wenn Sie einen nichtglibc-basierten Container verwenden möchten, müssen Sie:

  • Geben Sie Ihre eigene Kopie von Node.js an.
  • Fügen Sie Ihrem Bild eine Beschriftung hinzu, die dem Agent mitteilt, wo die Node.js Binärdatei gefunden werden soll.
  • Stellen Sie weitere Abhängigkeiten bereit, von denen Azure-Pipelines abhängig sind: bash, sudo, , whichund groupadd.

Liefern Sie Ihre eigene Node.js

Wenn Sie einen nichtglibc-basierten Container verwenden, sind Sie für das Hinzufügen einer Node-Binärdatei zu Ihrem Container verantwortlich. Node.js 18 ist eine sichere Wahl. Beginnen Sie mit dem node:18-alpine Bild.

Informieren des Agents über Node.js

Der Agent liest die Containerbezeichnung "com.azure.dev.pipelines.handler.node.path". Wenn diese Bezeichnung vorhanden ist, muss sie der Pfad zur Node.js Binärdatei sein.

Fügen Sie z. B. in einem Image basierend auf node:18-alpineIhrer Dockerfile-Datei die folgende Zeile hinzu:

LABEL "com.azure.dev.pipelines.agent.handler.node.path"="/usr/local/bin/node"

Hinzufügen von erforderlichen Paketen

Azure Pipelines geht davon aus, dass ein bash-basiertes System mit gängigen administrativen Paketen installiert ist. Insbesondere Alpine Linux verfügt nicht über mehrere der benötigten Pakete. Installieren Sie , sudo, und shadow decken Sie bashdie grundlegenden Anforderungen ab.

RUN apk add bash sudo shadow

Wenn Sie von In-Box- oder Marketplace-Aufgaben abhängen, stellen Sie auch die erforderlichen Binärdateien zur Verfügung.

Vollständiges Dockerfile-Beispiel

FROM node:18-alpine

RUN apk add --no-cache --virtual .pipeline-deps readline linux-pam \
  && apk add bash sudo shadow \
  && apk del .pipeline-deps

LABEL "com.azure.dev.pipelines.agent.handler.node.path"="/usr/local/bin/node"

CMD [ "node" ]