Compartir vía


Trabajos de contenedor en canalizaciones YAML

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

En este artículo se explican los trabajos de contenedor en Azure Pipelines.

De forma predeterminada, los trabajos de Azure Pipelines se ejecutan directamente en las máquinas host donde está instalado el agente. Los trabajos del agente hospedado son cómodos, requieren poca configuración inicial e infraestructura para mantener y son adecuadas para proyectos básicos.

Si desea tener más control sobre el contexto de la tarea, puede definir y ejecutar trabajos en contenedores. Los contenedores son una abstracción ligera sobre el sistema operativo host que proporciona aislamiento del host. Al ejecutar trabajos en contenedores, puede seleccionar las versiones exactas de los sistemas operativos, las herramientas y las dependencias que requiere la compilación.

Los agentes de Linux y Windows pueden ejecutar trabajos de canalización directamente en el host o en contenedores. Los trabajos de contenedor no están disponibles en macOS.

En el caso de un trabajo de contenedor, el agente primero captura e inicia el contenedor. A continuación, cada paso del trabajo se ejecuta dentro del contenedor.

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

Requisitos y limitaciones

Los siguientes requisitos y limitaciones se aplican a los hosts o contenedores del agente de Azure Pipelines.

Hosts del agente

  • Solo las imágenes de windows-* y ubuntu-* admiten la ejecución de contenedores. Las macos-* imágenes no admiten la ejecución de contenedores.
  • Para ejecutar contenedores, los hosts del agente de Windows y Linux deben tener Docker instalado y deben tener permiso para acceder al demonio de Docker.
  • Los contenedores no se admiten cuando el agente ya se está ejecutando dentro de un contenedor. No se pueden tener contenedores anidados.

Contenedores

Los contenedores basados en Linux tienen los siguientes requisitos. Para obtener soluciones alternativas, consulte Contenedores no basados englibc.

  • Bash instalado
  • Biblioteca gnu C (glibc) basada en
  • No ENTRYPOINT
  • Proporcionar USER acceso a groupadd y otros comandos con privilegios sin usar sudo
  • Puede ejecutar Node.js, que proporciona el agente.

    Nota:

    Node.js debe estar preinstalado para contenedores de Linux en hosts de Windows.

Algunos contenedores eliminados disponibles en Docker Hub, especialmente contenedores basados en Alpine Linux, no cumplen estos requisitos. Es posible que los contenedores con un ENTRYPOINT no funcionen porque Azure Pipelines docker create y docker exec esperan que el contenedor esté siempre en funcionamiento.

Ejemplos de trabajos únicos

En los ejemplos siguientes se define un contenedor de Windows o Linux para un solo trabajo.

En el ejemplo sencillo siguiente se define un contenedor de Linux:

pool:
  vmImage: 'ubuntu-latest'

container: ubuntu:18.04

steps:
- script: printenv

En el ejemplo anterior se indica al sistema que capture la ubuntu imagen etiquetada 18.04 desde Docker Hub y, a continuación, inicie el contenedor. El printenv comando se ejecuta dentro del ubuntu:18.04 contenedor.

Varios trabajos

Puede usar contenedores para ejecutar el mismo paso en varios trabajos. En el ejemplo siguiente se ejecuta el mismo paso en varias versiones de Ubuntu Linux. No es necesario mencionar la jobs palabra clave porque solo se define un solo trabajo.

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

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

Un trabajo de contenedor usa el archivo de configuración de Docker del agente host subyacente para la autorización del registro de imágenes. Este archivo cierra la sesión al final de la inicialización del contenedor del registro de Docker. Es posible que se denieguen las extracción de imágenes del Registro para los trabajos de contenedor posteriores porque unauthorized authentication otro trabajo que se ejecuta en paralelo ya ha cerrado el archivo de configuración de Docker.

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

export DOCKER_CONFIG=./.docker

Opciones de inicio

Puede especificar options para controlar el inicio del contenedor, como en el ejemplo siguiente:

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

steps:
- script: echo hello

La ejecución docker create --help proporciona la lista de opciones que puede pasar a la invocación de Docker. No está garantizado que todas estas opciones funcionen con Azure DevOps. Compruebe primero si puede usar una container propiedad para lograr el mismo objetivo.

Para más información, consulte la referencia de comandos docker create y la definición resources.containers.container en la referencia de esquema YAML de Azure DevOps.

Definición de contenedor reutilizable

En el ejemplo siguiente se definen los contenedores de la resources sección y, a continuación, se hace referencia a ellos por sus alias asignados. La jobs palabra clave aparece explícitamente para mayor claridad.

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

Puntos de conexión del servicio

Puede hospedar contenedores en otros registros que en Docker Hub público. Para hospedar una imagen en Azure Container Registry u otro registro de contenedor privado, incluido un registro privado de Docker Hub, agregue una conexión de servicio para acceder al registro. A continuación, puede hacer referencia al punto de conexión en la definición del contenedor.

Conexión privada de Docker Hub:

container:
  image: registry:ubuntu1804
  endpoint: private_dockerhub_connection

Conexión de Azure Container Registry:

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

Nota:

Azure Pipelines no puede configurar una conexión de servicio para Amazon Elastic Container Registry (ECR), ya que Amazon ECR requiere otras herramientas de cliente para convertir credenciales de AWS en algo que Docker puede usar para autenticarse.

Contenedores no basados englibc

El agente de Azure Pipelines proporciona una copia de Node.js, que es necesaria para ejecutar tareas y scripts. Para obtener información sobre la versión de Node.js de un agente hospedado, consulte Agentes hospedados por Microsoft.

La versión de Node.js se compila en el entorno de ejecución de C usado en la nube hospedada, normalmente glibc. Algunas variantes de Linux usan otros entornos de ejecución de C. Por ejemplo, Alpine Linux usa musl.

Si desea usar un contenedor no basado englibc, debe hacer lo siguiente:

  • Proporcione su propia copia de Node.js.
  • Agregue una etiqueta a la imagen que indica al agente dónde encontrar el Node.js binario.
  • Proporcione otras dependencias de las que depende Azure Pipelines: bash, sudo, whichy groupadd.

Suministrar su propio Node.js

Si usa un contenedor no basado englibc, es responsable de agregar un archivo binario node al contenedor. Node.js 18 es una opción segura. Comience desde la node:18-alpine imagen.

Informar al agente sobre Node.js

El agente lee la etiqueta "com.azure.dev.pipelines.handler.node.path"de contenedor . Si esta etiqueta existe, debe ser la ruta de acceso al archivo binario de Node.js.

Por ejemplo, en una imagen basada en node:18-alpine, agregue la siguiente línea al Dockerfile:

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

Adición de paquetes necesarios

Azure Pipelines asume un sistema basado en Bash con paquetes administrativos comunes instalados. Alpine Linux en particular no incluye varios de los paquetes necesarios. Instale bash, sudoy shadow para cubrir las necesidades básicas.

RUN apk add bash sudo shadow

Si depende de cualquier tarea integrada o de Marketplace, proporcione también los archivos binarios que necesiten.

Ejemplo completo de Dockerfile

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