Definición de trabajos de contenedor (YAML)

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

De forma predeterminada, los trabajos se ejecutan en la máquina host donde está instalado el agente. Esto es práctico y normalmente adecuado para los proyectos que están empezando a adoptar Azure Pipelines. Con el tiempo, es posible que quiera tener más control sobre el contexto donde se ejecutan las tareas. Las canalizaciones YAML ofrecen trabajos de contenedor para este nivel de control.

En Linux y Windows, los trabajos se pueden ejecutar en el host o en un contenedor. (En macOS y Red Hat Enterprise Linux 6, los trabajos de contenedor no están disponibles). Los contenedores proporcionan aislamiento del host y permiten anclar versiones específicas de herramientas y dependencias. Los trabajos de host requieren menos configuración inicial e infraestructura para mantener.

Los contenedores ofrecen una abstracción ligera sobre el sistema operativo host. Puede seleccionar las versiones exactas de los sistemas operativos, las herramientas y las dependencias que requiere la compilación. Al especificar un contenedor en la canalización, el agente primero capturará e iniciará el contenedor. A continuación, cada paso del trabajo se ejecutará dentro del contenedor. No puede tener contenedores anidados. Los contenedores no se admiten cuando un agente ya se está ejecutando dentro de un contenedor.

Si necesita un control específico en el nivel de paso individual, los destinos de paso le permiten elegir contenedor u host para cada paso.

Requisitos

Contenedores basados en Linux

El Azure Pipelines requiere algunas cosas en contenedores basados en Linux:

  • Bash
  • basado en glibc
  • Puede ejecutar Node.js (que proporciona el agente)
  • No define un ENTRYPOINT
  • USER tiene acceso a groupadd y otros comandos de privilegios sin sudo

Y en el host del agente:

  • Asegúrese de que Docker está instalado
  • El agente debe tener permiso para acceder al demonio de Docker.

Asegúrese de que el contenedor tiene disponibles cada una de estas herramientas. Algunos de los contenedores extremadamente desmontados disponibles en Docker Hub, especialmente los basados en Alpine Linux, no cumplen estos requisitos mínimos. Es posible que los contenedores con un no funcionen, ya que Azure Pipelines un contenedor en espera y una serie de comandos que esperan que el contenedor esté siempre en ENTRYPOINTdocker createdocker exec funcionamiento.

Nota

En Windows contenedores de Linux basados en Node.js deben estar preinstalados.

Contenedores de Windows

Azure Pipelines también puede ejecutar Windows Contenedores. Windows server versión 1803 o posterior es necesario. Docker debe estar instalado. Asegúrese de que el agente de canalizaciones tiene permiso para acceder al demonio de Docker.

El Windows debe admitir la ejecución de Node.js. Falta una base Windows contenedor de Nano Server que faltan dependencias necesarias para ejecutar Node.

Agentes hospedados

Solo las windows-2019 imágenes ubuntu-* y admiten contenedores en ejecución. La imagen de macOS no admite la ejecución de contenedores.

Trabajo único

Un ejemplo sencillo:

pool:
  vmImage: 'ubuntu-18.04'

container: ubuntu:18.04

steps:
- script: printenv

Esto indica al sistema que obtenga la imagen etiquetada Docker Hub y, a ubuntu18.04 continuación, inicie el contenedor. ubuntu Cuando se printenv ejecute el comando, se realizará dentro del ubuntu:18.04 contenedor.

Un Windows ejemplo:

pool:
  vmImage: 'windows-2019'

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

steps:
- script: set

Nota

Windows requiere que la versión del kernel del host y el contenedor coincidan. Puesto que en este ejemplo se Windows imagen de 2019, se usará la 2019 etiqueta para el contenedor.

Varios trabajos

Los contenedores también son útiles para ejecutar los mismos pasos en varios trabajos. En el ejemplo siguiente, los mismos pasos se ejecutan en varias versiones de Ubuntu Linux. (Y no tenemos que mencionar la palabra clave , ya que solo hay un jobs único trabajo definido).

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

Puntos de conexión

Los contenedores se pueden hospedar en registros distintos de Docker Hub. Para hospedar una imagen en Azure Container Registry otro registro de contenedor privado, agregue una conexión de servicio al registro privado. A continuación, puede hacer referencia a ella en una especificación de contenedor:

container:
  image: registry:ubuntu1604
  endpoint: private_dockerhub_connection

steps:
- script: echo hello

o

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

steps:
- script: echo hello

También pueden funcionar otros registros de contenedor. Amazon ECR no funciona actualmente, ya que hay herramientas de cliente adicionales necesarias para convertir las credenciales de AWS en algo que Docker puede usar para autenticarse.

Nota

Red Hat Enterprise compilación de Linux 6 del agente no ejecutará el trabajo de contenedor. Elija otro tipo de Linux, como Red Hat Enterprise Linux 7 o posterior.

Opciones

Si necesita controlar el inicio del contenedor, puede especificar options .

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

steps:
- script: echo hello

La docker create --help ejecución le dará la lista de opciones admitidas. Puede usar cualquier opción disponible con el comando.

Definición de contenedor reutilizable

En el ejemplo siguiente, los contenedores se definen en la sección de recursos. A continuación, se hace referencia a cada contenedor más adelante, haciendo referencia a su alias asignado. (Aquí, enumeramos explícitamente la jobs palabra clave para mayor claridad).

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

Contenedores no basados en glibc

El Azure Pipelines proporciona una copia de Node.js, que es necesaria para ejecutar tareas y scripts. La versión de Node.js se compila en el entorno de ejecución de C que usamos en nuestra nube hospedada, normalmente glibc. Algunas variantes de Linux usan otros entornos de ejecución de C. Por ejemplo, Alpine Linux usa la tecnología .

Si desea usar un contenedor no basado en glibc como contenedor de trabajos, deberá organizar algunas cosas por su cuenta. En primer lugar, debe proporcionar su propia copia de Node.js. En segundo lugar, debe agregar una etiqueta a la imagen que le diga al agente dónde encontrar el Node.js binario. Por último, las acciones de Alpine no vienen con otras dependencias de las que Azure Pipelines depende: bash, sudo, which y groupadd.

Traiga su propia Node.js

Usted es responsable de agregar un binario de Nodo al contenedor. El nodo 14 es una opción segura. Puede empezar desde la node:14-alpine imagen.

Informe al agente sobre Node.js

El agente leerá una etiqueta de contenedor "com.azure.dev.pipelines.handler.node.path". Si esta etiqueta existe, debe ser la ruta de acceso al Node.js binario. Por ejemplo, en una imagen basada en node:10-alpine , agregue esta línea al Dockerfile:

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

Agregar requisitos

Azure Pipelines un sistema basado en Bash con paquetes de administración comunes instalados. Alpine Linux en particular no viene con varios de los paquetes necesarios. La bash instalación de , y sudoshadow cubrirá las necesidades básicas.

RUN apk add bash sudo shadow

Si depende de cualquier tarea de Marketplace o de la caja, también deberá proporcionar los archivos binarios que requieren.

Ejemplo completo de un dockerfile

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

Varios trabajos con grupos de agentes en un único agente hospedado

El trabajo de contenedor usa el agente de host subyacente Docker config.json para la autorización del registro de imágenes, que cierra la sesión al final de la inicialización del contenedor del registro de Docker. La autorización posterior de extracciones de imágenes del Registro podría denegarse para la "autenticación no autorizada" porque el archivo config.json de Docker registrado en el sistema para la autenticación ya lo ha cerrado uno de los otros trabajos de contenedor que se ejecutan en paralelo.

La solución es establecer la variable de entorno de Docker que es específica de cada servicio de grupo de agentes DOCKER_CONFIG que se ejecuta en el agente hospedado. Exporte DOCKER_CONFIG el en el script de runsvc.sh grupo de agentes:

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