Trabalhos de contêiner em dutos YAML

Serviços de DevOps do Azure | Azure DevOps Server 2022 - Azure DevOps Server 2019

Este artigo explica os trabalhos de contêiner no Azure Pipelines.

Por padrão, os trabalhos do Azure Pipelines são executados diretamente nas máquinas host onde o agente está instalado. Os trabalhos do agente hospedado são convenientes, exigem pouca configuração inicial e infraestrutura para manutenção e são adequados para projetos básicos.

Se quiser mais controle sobre o contexto da tarefa, você pode definir e executar trabalhos em contêineres. Os contêineres são uma abstração leve sobre o sistema operacional do host que fornece isolamento do host. Ao executar trabalhos em contêineres, você pode selecionar as versões exatas de sistemas operacionais, ferramentas e dependências que sua compilação exige.

Os agentes Linux e Windows podem executar trabalhos de pipeline diretamente no host ou em contêineres. Os trabalhos de contêiner não estão disponíveis no macOS.

Para um trabalho de contêiner, o agente primeiro busca e inicia o contêiner. Em seguida, cada etapa do trabalho é executada dentro do contêiner.

Se você precisar de um controle refinado no nível da etapa de construção individual, os destinos de etapa permitem que você escolha um contêiner ou host para cada etapa.

Pré-requisitos

  • Use um pipeline YAML. Os pipelines clássicos não suportam trabalhos de contêiner.
  • Use um agente Windows ou Ubuntu hospedado. Apenas windows-* e ubuntu-* agentes suportam a execução de contêineres. Os macos-* agentes não suportam a execução de contêineres.
  • Seu agente está configurado para trabalhos de contêiner.
    • Os agentes Windows e Linux devem ter o Docker instalado e precisam de permissão para acessar o daemon do Docker.
    • Os contêineres não são suportados quando o agente já está em execução dentro de um contêiner. Não é possível ter contêineres aninhados.

Requisitos adicionais do contentor

Os contêineres baseados em Linux têm os seguintes requisitos. Para obter soluções alternativas, consulte Contêineres não baseados em glibc.

  • Bash instalado
  • Baseado na Biblioteca GNU C (glibc)
  • Não ENTRYPOINT
  • Fornecer USER acesso a groupadd e outros comandos privilegiados sem usar sudo
  • Pode executar Node.js, que o agente fornece

    Nota

    Node.js deve ser pré-instalado para contêineres Linux em hosts Windows.

Alguns contêineres despojados disponíveis no Docker Hub, especialmente contêineres baseados no Alpine Linux, não atendem a esses requisitos. Os contêineres com um ENTRYPOINT podem não funcionar porque o Azure Pipelines docker create espera docker exec que o contêiner esteja sempre ativo e em execução.

Exemplos de emprego único

Os exemplos a seguir definem um contêiner Windows ou Linux para um único trabalho.

O exemplo simples a seguir define um contêiner Linux:

pool:
  vmImage: 'ubuntu-latest'

container: ubuntu:18.04

steps:
- script: printenv

O exemplo anterior diz ao sistema para buscar a ubuntu imagem marcada 18.04 no Docker Hub e, em seguida, iniciar o contêiner. O printenv comando é executado dentro do ubuntu:18.04 contêiner.

Vários trabalhos

Você pode usar contêineres para executar a mesma etapa em vários trabalhos. O exemplo a seguir executa a mesma etapa em várias versões do Ubuntu Linux. Você não precisa mencionar a jobs palavra-chave porque apenas um único trabalho é definido.

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

Vários trabalhos com pools de agentes em um único host de agente

Um trabalho de contêiner usa o arquivo de configuração do Docker do agente de host subjacente para autorização de registro de imagem. Esse arquivo sai no final da inicialização do contêiner do Registro do Docker. As imagens do Registro para trabalhos de contêiner subsequentes podem ser negadas porque unauthorized authentication outro trabalho em execução em paralelo já desconectou o arquivo de configuração do Docker.

A solução é definir uma variável DOCKER_CONFIG de ambiente do Docker específica para cada pool de agentes em execução no agente hospedado. Exporte o DOCKER_CONFIG script de runsvc.sh de cada pool de agentes da seguinte maneira:

export DOCKER_CONFIG=./.docker

Opções de inicialização

Você pode especificar options para controlar a inicialização do contêiner, como no exemplo a seguir:

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

steps:
- script: echo hello

A execução docker create --help fornece a lista de opções que você pode passar para a chamada do Docker. Nem todas essas opções têm garantia de funcionar com o Azure DevOps. Verifique primeiro se você pode usar um container imóvel para atingir o mesmo objetivo.

Para obter mais informações, consulte a referência de comando docker create e a definição resources.containers.container na referência de esquema YAML do Azure DevOps.

Definição de recipiente reutilizável

O exemplo a seguir define os contêineres na seção e, em seguida, faz referência a resources eles por seus aliases atribuídos. A jobs palavra-chave está explicitamente listada para maior clareza.

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

Pontos finais de serviço

Você pode hospedar contêineres em outros registros que não o Docker Hub público. Para hospedar uma imagem no Registro de Contêiner do Azure ou outro registro de contêiner privado, incluindo um registro privado do Docker Hub, adicione uma conexão de serviço para acessar o Registro. Em seguida, você pode fazer referência ao ponto de extremidade na definição de contêiner.

Conexão privada do Docker Hub:

container:
  image: registry:ubuntu1804
  endpoint: private_dockerhub_connection

Conexão do Registro de Contêiner do Azure:

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

Nota

O Azure Pipelines não pode configurar uma conexão de serviço para o Amazon Elastic Container Registry (ECR), porque o Amazon ECR requer outras ferramentas de cliente para converter credenciais da AWS em algo que o Docker possa usar para autenticar.

Contentores não baseados em glibc

O agente do Azure Pipelines fornece uma cópia do Node.js, que é necessária para executar tarefas e scripts. Para descobrir a versão do Node.js para um agente hospedado, consulte Agentes hospedados pela Microsoft.

A versão do Node.js compila em relação ao tempo de execução C usado na nuvem hospedada, normalmente glibc. Algumas variantes do Linux usam outros tempos de execução C. Por exemplo, o Alpine Linux usa musl.

Se você quiser usar um contêiner não baseado em glibc, você precisa:

  • Forneça a sua própria cópia do Node.js.
  • Adicione um rótulo à sua imagem informando ao agente onde encontrar o binário Node.js.
  • Forneça outras dependências das quais o Azure Pipelines depende: bash, sudo, whiche groupadd.

Forneça o seu próprio Node.js

Se você usar um contêiner não baseado em glibc, será responsável por adicionar um binário de nó ao contêiner. Node.js 18 anos é uma escolha segura. Comece pela node:18-alpine imagem.

Informe o agente sobre Node.js

O agente lê o rótulo "com.azure.dev.pipelines.handler.node.path"do contêiner. Se esse rótulo existir, ele deve ser o caminho para o binário Node.js.

Por exemplo, em uma imagem baseada em node:18-alpine, adicione a seguinte linha ao seu Dockerfile:

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

Adicionar pacotes necessários

O Azure Pipelines assume um sistema baseado em Bash com pacotes administrativos comuns instalados. O Alpine Linux, em particular, não vem com vários dos pacotes necessários. Instale bash, sudoe shadow para cobrir as necessidades básicas.

RUN apk add bash sudo shadow

Se você depender de alguma tarefa da caixa de entrada ou do Marketplace, forneça também os binários necessários.

Exemplo completo do 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" ]