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 los equipos host en los que está instalado el agente. Los trabajos del agente hospedado son cómodos, requieren poca configuración inicial e infraestructura para mantener y son adecuados 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 a nivel de paso de compilación individual, los destinos de paso le permiten elegir el contenedor o el host de cada paso.
Requisitos previos
- Use una canalización YAML. Las canalizaciones clásicas no admiten trabajos de contenedor.
- Use un agente de Windows o Ubuntu hospedado. Solo los agentes de
windows-*
yubuntu-*
admiten la ejecución de contenedores. Los agentesmacos-*
no admiten la ejecución de contenedores. - El agente está configurado para trabajos de contenedor.
- Los agentes de Windows y Linux deben tener Docker instalado y necesitan permiso para acceder al demonio de Docker.
- No se admiten contenedores cuando el agente ya se ejecuta dentro de un contenedor. No se pueden tener contenedores anidados.
Requisitos de contenedor adicionales
Los contenedores basados en Linux tienen los siguientes requisitos. Para obtener soluciones alternativas, consulte Contenedores no basados en glibc.
- Bash instalado
- Basado en biblioteca GNU C (glibc)
- No
ENTRYPOINT
- Proporciona
USER
con acceso agroupadd
y otros comandos con privilegios sin usarsudo
- Puede ejecutar Node.js, que proporciona el agente
Nota:
En el caso de los contenedores de Linux basados en hosts de Windows, Node.js debe estar preinstalado.
Algunos de los contenedores eliminados disponibles en Docker Hub, especialmente aquellos 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
El ejemplo anterior indica al sistema que capture la imagen de ubuntu
etiquetada como 18.04
de Docker Hub y, que, luego, inicie el contenedor. El comando printenv
se ejecuta dentro del contenedor ubuntu:18.04
.
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 palabra clave jobs
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 deniegue la unauthorized authentication
de extracciones de imágenes del Registro para los trabajos de contenedor posteriores porque 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 de entorno DOCKER_CONFIG
de Docker específica de cada grupo de agentes que se ejecuta en el agente hospedado. Exporte DOCKER_CONFIG
en cada script runsvc.sh de cada grupo de agentes como se indica:
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 de 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 propiedad container
para lograr el mismo objetivo.
Para obtener más información, consulte la referencia del comando 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 sección resources
y, a continuación, se hace referencia a ellos por sus alias asignados. Por claridad, aquí se muestra explícitamente la palabra clave jobs
.
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 distintos de los registros de Docker Hub públicos. Para hospedar una imagen en Azure Container Registry u otro registro de contenedor privado, incluido un registro de Docker Hub privado, 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 en glibc
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 tiempo de ejecución de C que se usa 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 en glibc, debe hacer lo siguiente:
- Proporcione su propia copia de Node.js.
- Agregue una etiqueta a la imagen que indique al agente dónde encontrar el archivo binario Node.js.
- Proporcione otras dependencias de las que depende Azure Pipelines:
bash
,sudo
,which
ygroupadd
.
Proporcione su propio Node.js
Si usa un contenedor no basado en glibc, es responsable de agregar un archivo binario de nodo al contenedor. Node.js 18 es una opción segura. Empiece por la imagen node:18-alpine
.
Informar al agente sobre Node.js
El agente lee la etiqueta de contenedor "com.azure.dev.pipelines.handler.node.path"
. 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 línea siguiente al Dockerfile:
LABEL "com.azure.dev.pipelines.agent.handler.node.path"="/usr/local/bin/node"
Adición de paquetes necesarios
Azure Pipelines da por hecho un sistema basado en Bash con paquetes administrativos comunes instalados. Alpine Linux en particular no incluye varios de los paquetes necesarios. Instale bash
, sudo
y 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 estos requieran.
Ejemplo de 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" ]