Processi del contenitore nelle pipeline YAML

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

Questo articolo illustra i processi dei contenitori in Azure Pipelines.

Per impostazione predefinita, i processi di Azure Pipelines vengono eseguiti direttamente nei computer host in cui è installato l'agente. I processi dell'agente ospitato sono pratici, richiedono una piccola configurazione iniziale e un'infrastruttura da gestire e sono particolarmente adatti per i progetti di base.

Se si vuole un maggiore controllo sul contesto dell'attività, è possibile definire ed eseguire processi nei contenitori. I contenitori sono un'astrazione leggera sul sistema operativo host che fornisce l'isolamento dall'host. Quando si eseguono processi in contenitori, è possibile selezionare le versioni esatte dei sistemi operativi, degli strumenti e delle dipendenze richieste dalla compilazione.

Gli agenti Linux e Windows possono eseguire processi di pipeline direttamente nell'host o nei contenitori. I processi del contenitore non sono disponibili in macOS.

Per un processo contenitore, l'agente recupera prima e avvia il contenitore. Ogni passaggio del processo viene quindi eseguito all'interno del contenitore.

Se è necessario un controllo granulare a livello di singolo passaggio di compilazione, le destinazioni dei passaggi consentono di scegliere un contenitore o un host per ogni passaggio.

Prerequisiti

  • Usare una pipeline YAML. Le pipeline classiche non supportano i processi del contenitore.
  • Usare un agente Windows o Ubuntu ospitato. Solo windows-* gli agenti e ubuntu-* supportano l'esecuzione di contenitori. Gli macos-* agenti non supportano l'esecuzione di contenitori.
  • L'agente è configurato per i processi del contenitore.
    • Gli agenti Windows e Linux devono avere Docker installato e devono avere l'autorizzazione per accedere al daemon Docker.
    • I contenitori non sono supportati quando l'agente è già in esecuzione all'interno di un contenitore. Non è possibile avere contenitori annidati.

Requisiti aggiuntivi per i contenitori

I contenitori basati su Linux hanno i requisiti seguenti. Per le soluzioni alternative, vedere Contenitori basati su Nonglibc.

  • Bash installato
  • Libreria GNU C (glibc) basata su
  • No ENTRYPOINT
  • Fornire USER l'accesso a groupadd e altri comandi con privilegi senza usare sudo
  • Può eseguire Node.js, che l'agente fornisce

    Nota

    Node.js deve essere preinstallato per i contenitori Linux in host Windows.

Alcuni contenitori rimossi disponibili nell'hub Docker, in particolare i contenitori basati su Alpine Linux, non soddisfano questi requisiti. I contenitori con un ENTRYPOINT potrebbe non funzionare perché Azure Pipelines docker create prevede docker exec che il contenitore sia sempre operativo.

Esempi di singoli processi

Gli esempi seguenti definiscono un contenitore Windows o Linux per un singolo processo.

L'esempio semplice seguente definisce un contenitore Linux:

pool:
  vmImage: 'ubuntu-latest'

container: ubuntu:18.04

steps:
- script: printenv

L'esempio precedente indica al sistema di recuperare l'immagine ubuntu contrassegnata 18.04 dall'hub Docker e quindi avviare il contenitore. Il printenv comando viene eseguito all'interno del ubuntu:18.04 contenitore.

Più processi

È possibile usare i contenitori per eseguire lo stesso passaggio in più processi. L'esempio seguente esegue lo stesso passaggio in più versioni di Ubuntu Linux. Non è necessario menzionare la jobs parola chiave perché è definito solo un singolo processo.

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

Più processi con pool di agenti in un singolo host agente

Un processo contenitore usa il file di configurazione Docker dell'agente host sottostante per l'autorizzazione del Registro immagini. Questo file si disconnette alla fine dell'inizializzazione del contenitore del registro Docker. È possibile che venga negato il pull delle immagini del Registro di unauthorized authentication sistema per i processi contenitore successivi perché un altro processo in esecuzione in parallelo ha già disconnesso il file di configurazione Docker.

La soluzione consiste nell'impostare una variabile DOCKER_CONFIG di ambiente Docker specifica per ogni pool di agenti in esecuzione nell'agente ospitato. Esportare lo DOCKER_CONFIG script di runsvc.sh di ogni pool di agenti come indicato di seguito:

export DOCKER_CONFIG=./.docker

Opzioni di avvio

È possibile specificare options di controllare l'avvio del contenitore, come nell'esempio seguente:

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

steps:
- script: echo hello

L'esecuzione docker create --help offre l'elenco delle opzioni che è possibile passare alla chiamata a Docker. Non tutte queste opzioni sono garantite per l'uso con Azure DevOps. Controllare prima di tutto se è possibile usare una container proprietà per raggiungere lo stesso obiettivo.

Per altre informazioni, vedere le informazioni di riferimento sui comandi docker create e la definizione resources.containers.container nella guida di riferimento allo schema YAML di Azure DevOps.

Definizione di contenitore riutilizzabile

L'esempio seguente definisce i contenitori nella resources sezione e quindi li fa riferimento in base agli alias assegnati. La jobs parola chiave è elencata in modo esplicito per maggiore chiarezza.

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

Endpoint di servizio

È possibile ospitare contenitori in altri registri rispetto all'hub Docker pubblico. Per ospitare un'immagine in Registro Azure Container o in un altro registro contenitori privato, incluso un registro privato dell'hub Docker, aggiungere una connessione al servizio per accedere al Registro di sistema. È quindi possibile fare riferimento all'endpoint nella definizione del contenitore.

Connessione dell'hub Docker privato:

container:
  image: registry:ubuntu1804
  endpoint: private_dockerhub_connection

Registro Azure Container connessione:

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

Nota

Azure Pipelines non è in grado di configurare una connessione al servizio per Amazon Elastic Container Registry (ECR), perché Amazon ECR richiede altri strumenti client per convertire le credenziali AWS in qualcosa che Docker può usare per l'autenticazione.

Contenitori basati su nonglibc

L'agente di Azure Pipelines fornisce una copia di Node.js, necessaria per eseguire attività e script. Per scoprire la versione di Node.js per un agente ospitato, vedere Agenti ospitati da Microsoft.

La versione di Node.js viene compilata in base al runtime C usato nel cloud ospitato, in genere glibc. Alcune varianti linux usano altri runtime C. Ad esempio, Alpine Linux usa musl.

Se si vuole usare un contenitore non basato su eventi, è necessario:If you want to use a nonglibc-based container, you need to:

  • Fornire una copia personalizzata di Node.js.
  • Aggiungere un'etichetta all'immagine che indica all'agente dove trovare il file binario Node.js.
  • Fornire altre dipendenze da cui Azure Pipelines dipende da: bash, sudowhich, e groupadd.

Fornire il proprio Node.js

Se si usa un contenitore non basato su log, si è responsabili dell'aggiunta di un file binario Node al contenitore. Node.js 18 è una scelta sicura. Iniziare dall'immagine node:18-alpine .

Informazioni sull'agente su Node.js

L'agente legge l'etichetta "com.azure.dev.pipelines.handler.node.path"del contenitore . Se questa etichetta esiste, deve essere il percorso del file binario Node.js.

Ad esempio, in un'immagine basata su node:18-alpineaggiungere la riga seguente al Dockerfile:

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

Aggiungere i pacchetti necessari

Azure Pipelines presuppone un sistema basato su Bash con pacchetti amministrativi comuni installati. Alpine Linux in particolare non include diversi pacchetti necessari. Installare bash, sudoe shadow per soddisfare le esigenze di base.

RUN apk add bash sudo shadow

Se si dipende da qualsiasi attività in-box o marketplace, specificare anche i file binari necessari.

Esempio di Dockerfile completo

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