Definieren von Containeraufträgen (YAML)

Azure Pipelines | Azure DevOps Server 2020 | Azure DevOps Server 2019

Standardmäßig werden Aufträge auf dem Hostcomputer ausgeführt, auf dem der Agent installiert ist. Dies ist praktisch und eignet sich in der Regel gut für Projekte, die gerade erst beginnen, Azure Pipelines. Im Laufe der Zeit können Sie feststellen, dass Sie mehr Kontrolle über den Kontext wünschen, in dem Ihre Aufgaben ausgeführt werden. YAML-Pipelines bieten Containeraufträge für diese Steuerungsebene.

Unter Linux und Windows Agents können Aufträge auf dem Host oder in einem Container ausgeführt werden. (Unter macOS und Red Hat Enterprise Linux 6 sind Keine Containeraufträge verfügbar.) Container bieten Isolation vom Host und ermöglichen es Ihnen, bestimmte Versionen von Tools und Abhängigkeiten anheften. Hostaufträge erfordern weniger anfängliche Einrichtung und Infrastruktur für die Wartung.

Container bieten eine einfache Abstraktion über das Hostbetriebssystem. Sie können die genauen Versionen von Betriebssystemen, Tools und Abhängigkeiten auswählen, die ihr Build erfordert. Wenn Sie einen Container in Ihrer Pipeline angeben, ruft der Agent zuerst den Container ab und startet ihn. Anschließend wird jeder Schritt des Auftrags im Container ausgeführt. Geschachtelte Container sind nicht möglich. Container werden nicht unterstützt, wenn ein Agent bereits in einem Container ausgeführt wird.

Wenn Sie eine fein abgrenzende Steuerung auf Einzelschrittebene benötigen, können Sie mit Schrittzielen container oder host für jeden Schritt auswählen.

Requirements (Anforderungen)

Linux-basierte Container

Das Azure Pipelines-System erfordert einige Dinge in Linux-basierten Containern:

  • Bash
  • glibc-basiert
  • Kann eine Node.js ausführen (die der Agent an stellt)
  • Definiert keine ENTRYPOINT
  • USER hat Zugriff auf groupadd - und andere Berechtigungsbefehle ohne sudo

Und auf Ihrem Agent-Host:

  • Sicherstellen, dass Docker installiert ist
  • Der Agent muss über die Berechtigung für den Zugriff auf den Docker-Daemon verfügen.

Stellen Sie sicher, dass in Ihrem Container jedes dieser Tools verfügbar ist. Einige der extrem entfernten Container, die auf Docker Hub verfügbar sind, insbesondere solche, die auf Alpine Linux basieren, erfüllen diese Mindestanforderungen nicht. Container mit einem funktionieren möglicherweise nicht, da Azure Pipelines ein wartenden Container und eine Reihe von Befehlen ist, die erwarten, dass der Container ENTRYPOINTdocker create immer ausgeführt docker exec wird.

Hinweis

Für Windows Linux-Container müssen Node.js vorinstalliert sein.

Windows-Container

Azure Pipelines kann auch Windows Container ausführen. Windows Serverversion 1803 oder höher ist erforderlich. Docker muss installiert sein. Stellen Sie sicher, dass Ihr Pipeline-Agent über die Berechtigung für den Zugriff auf den Docker-Daemon verfügt.

Der Windows-Container muss die Ausführung von Node.js. In einem Windows Nano Server-Container fehlen Abhängigkeiten, die zum Ausführen von Node erforderlich sind.

Gehostete Agents

Nur windows-2019 - und ubuntu-* -Images unterstützen das Ausführen von Containern. Das macOS-Image unterstützt das Ausführen von Containern nicht.

Einzelner Auftrag

Ein einfaches Beispiel:

pool:
  vmImage: 'ubuntu-18.04'

container: ubuntu:18.04

steps:
- script: printenv

Dies weist das System an, das mit tags versehene Image Docker Hub ubuntu und dann den Container zu 18.04 starten. ubuntu Wenn der printenv Befehl ausgeführt wird, geschieht dies innerhalb des ubuntu:18.04 Containers.

Ein Windows Beispiel:

pool:
  vmImage: 'windows-2019'

container: mcr.microsoft.com/windows/servercore:ltsc2019

steps:
- script: set

Hinweis

Windows erfordert, dass die Kernelversion des Hosts und des Containers übereinstimmen. Da in diesem Beispiel das image Windows 2019 verwendet wird, verwenden wir das 2019 -Tag für den Container.

Mehrere Aufträge

Container sind auch nützlich, um die gleichen Schritte in mehreren Aufträgen ausführen zu können. Im folgenden Beispiel werden die gleichen Schritte in mehreren Versionen von Ubuntu Linux. (Und wir müssen das Schlüsselwort nicht erwähnen, da nur ein jobs einzelner Auftrag definiert ist.)

pool:
  vmImage: 'ubuntu-18.04'

strategy:
  matrix:
    ubuntu14:
      containerImage: ubuntu:14.04
    ubuntu16:
      containerImage: ubuntu:16.04
    ubuntu18:
      containerImage: ubuntu:18.04

container: $[ variables['containerImage'] ]

steps:
- script: printenv

Endpunkte

Container können auf anderen Registrierungen gehostet werden als Docker Hub. Um ein Image in einer Azure Container Registry oder einer anderen privaten Containerregistrierung zu hosten, fügen Sie der privaten Registrierung eine Dienstverbindung hinzu. Anschließend können Sie in einer Containerspezifikation auf sie verweisen:

container:
  image: registry:ubuntu1604
  endpoint: private_dockerhub_connection

steps:
- script: echo hello

oder

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

steps:
- script: echo hello

Andere Container-Registrierungen können ebenfalls funktionieren. Amazon ECR funktioniert derzeit nicht, da zusätzliche Clienttools erforderlich sind, um AWS-Anmeldeinformationen in etwas zu konvertieren, das Docker für die Authentifizierung verwenden kann.

Hinweis

Der Red Hat Enterprise Linux 6-Build des Agents wird keinen Containerauftrag ausführen. Wählen Sie eine andere Linux-Variante aus, z. B. Red Hat Enterprise Linux 7 oder höher.

Tastatur

Wenn Sie den Containerstart steuern müssen, können Sie options angeben.

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

steps:
- script: echo hello

Wenn docker create --help Sie ausführen, erhalten Sie eine Liste der unterstützten Optionen. Sie können jede option verwenden, die mit dem Befehl verfügbar ist.

Wiederverwendbare Containerdefinition

Im folgenden Beispiel werden die Container im Abschnitt resources definiert. Auf jeden Container wird später verwiesen, indem auf seinen zugewiesenen Alias verwiesen wird. (Hier listen wir aus Gründen der Übersichtlichkeit explizit jobs das Schlüsselwort auf.)

resources:
  containers:
  - container: u14
    image: ubuntu:14.04

  - container: u16
    image: ubuntu:16.04

  - container: u18
    image: ubuntu:18.04

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

  strategy:
    matrix:
      ubuntu14:
        containerResource: u14
      ubuntu16:
        containerResource: u16
      ubuntu18:
        containerResource: u18

  container: $[ variables['containerResource'] ]

  steps:
  - script: printenv

Nicht glibcbasierte Container

Der Azure Pipelines-Agent stellt eine Kopie der Node.js zur Verfügung, die zum Ausführen von Aufgaben und Skripts erforderlich ist. Die Version von Node.js wird für die C-Runtime kompiliert, die wir in unserer gehosteten Cloud verwenden, in der Regel glibc. Einige Varianten von Linux verwenden andere C-Runtimes. Alpine Linux verwendet z. B. "besenl".

Wenn Sie einen nicht glibc-basierten Container als Auftragscontainer verwenden möchten, müssen Sie einige Dinge selbst anordnen. Zunächst müssen Sie eine eigene Kopie des Node.js. Zweitens müssen Sie ihrem Image eine Bezeichnung hinzufügen, die dem Agent anknNode.js finden soll. Schließlich enthält Stock Alpine keine anderen Abhängigkeiten, von denen Azure Pipelines abhängig sind: bash, sudo, which und groupadd.

Bring Your Own Node.js

Sie sind für das Hinzufügen einer Node-Binärdatei zu Ihrem Container verantwortlich. Knoten 14 ist eine sichere Wahl. Sie können mit dem Image node:14-alpine beginnen.

Informieren Sie den Agent ü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 binären Node.js sein. Fügen Sie beispielsweise in einem Image, das auf node:10-alpine basiert, ihrer Dockerfile-Datei die folgende Zeile hinzu:

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

Anforderungen hinzufügen

Azure Pipelines wird von einem Bash-basierten System ausgegangen, auf dem allgemeine Verwaltungspakete installiert sind. Alpine Linux bietet insbesondere nicht mehrere der benötigten Pakete. Die Installation bash von , und deckt die sudoshadow grundlegenden Anforderungen ab.

RUN apk add bash sudo shadow

Wenn Sie von In-Box- oder Marketplace-Aufgaben abhängig sind, müssen Sie auch die benötigten Binärdateien zur Verfügung stellen.

Vollständiges Beispiel für eine Dockerfile-Datei

FROM node:10-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" ]

Mehrere Aufträge mit Agentpools auf einem einzelnen gehosteten Agent

Der Containerauftrag verwendet die zugrunde liegende Docker-Datei config.json des Host-Agents für die Imageregistrierungsautorisierung, die sich am Ende der Initialisierung des Docker-Registrierungscontainers abmelden. Die Nachfolgende Pullautorisierung des Registrierungsimages wird möglicherweise aufgrund einer "nicht autorisierten Authentifizierung" verweigert, da die im System für die Authentifizierung registrierte Docker-Datei "config.json" bereits von einem der anderen Containeraufträge abgemelgt wurde, die parallel ausgeführt werden.

Die Lösung besteht im Festlegen der Docker-Umgebungsvariablen, die für jeden Agentpooldienst spezifisch ist, DOCKER_CONFIG der auf dem gehosteten Agent ausgeführt wird. Exportieren Sie DOCKER_CONFIG den in das skript der runsvc.sh Agentpools:

#insert anything to set up env when running as a service
export DOCKER_CONFIG=./.docker