Definir trabalhos de contentor (YAML)

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

Por padrão, os trabalhos são executados na máquina host onde o agente está instalado. Isso é conveniente e normalmente adequado para projetos que estão apenas começando a adotar o Azure Pipelines. Com o tempo, você pode achar que deseja ter mais controle sobre o contexto em que suas tarefas são executadas. Os pipelines YAML oferecem trabalhos de contêiner para esse nível de controle.

Em agentes Linux e Windows, os trabalhos podem ser executados no host ou em um contêiner. (No macOS e no Red Hat Enterprise Linux 6, os trabalhos de contêiner não estão disponíveis.) Os contêineres fornecem isolamento do host e permitem fixar versões específicas de ferramentas e dependências. Os trabalhos de host exigem menos configuração inicial e infraestrutura para manutenção.

Os contêineres oferecem uma abstração leve sobre o sistema operacional host. Você pode selecionar as versões exatas de sistemas operacionais, ferramentas e dependências que sua compilação exige. Quando você especificar um contêiner em seu pipeline, o agente primeiro buscará e iniciará o contêiner. Em seguida, cada etapa do trabalho será executada dentro do contêiner. Não é possível ter contêineres aninhados. Não há suporte para contêineres quando um agente já está em execução dentro de um contêiner.

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

Requisitos

Contêineres baseados em Linux

O sistema Azure Pipelines requer algumas coisas em contêineres baseados em Linux:

  • Bash
  • Baseado em glibc
  • Pode executar o Node.js (que o agente fornece)
  • Não define um ENTRYPOINT
  • USER tem acesso a groupadd e outros comandos de privilégios sem sudo

E no seu anfitrião agente:

  • Verifique se o Docker está instalado
  • O agente deve ter permissão para acessar o daemon do Docker

Certifique-se de que seu contêiner tenha cada uma dessas ferramentas disponíveis. Alguns dos contêineres despojados disponíveis no Docker Hub, especialmente aqueles baseados no Alpine Linux, não satisfazem esses requisitos mínimos. Os contêineres com um podem não funcionar, já que o Azure Pipelines será docker create um ENTRYPOINT contêiner aguardando e uma série de comandos, que esperam que o contêiner esteja sempre ativo e docker exec em execução.

Nota

Para contêineres Linux baseados em Windows, o Node.js deve ser pré-instalado.

Contentores do Windows

Os Pipelines do Azure também podem executar Contêineres do Windows. É necessário o Windows Server versão 1803 ou superior. O Docker deve estar instalado. Certifique-se de que seu agente de pipelines tenha permissão para acessar o daemon do Docker.

O contêiner do Windows deve suportar a execução do Node.js. Um contêiner base do Windows Nano Server está faltando dependências necessárias para executar o nó.

Agentes alojados

Apenas windows-2019 e ubuntu-* imagens suportam a execução de contêineres. A imagem do macOS não suporta contêineres em execução.

Emprego único

Um exemplo simples:

pool:
  vmImage: 'ubuntu-latest'

container: ubuntu:18.04

steps:
- script: printenv

Isso diz ao sistema para buscar a ubuntu imagem marcada 18.04 do Docker Hub e, em seguida, iniciar o contêiner. Quando o printenv comando for executado, isso acontecerá dentro do ubuntu:18.04 contêiner.

Um exemplo do Windows:

pool:
  vmImage: 'windows-2019'

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

steps:
- script: set

Nota

O Windows requer que a versão do kernel do host e do contêiner correspondam. Como este exemplo usa a imagem do Windows 2019, usaremos a 2019 tag para o contêiner.

Vários trabalhos

Os contêineres também são úteis para executar as mesmas etapas em vários trabalhos. No exemplo a seguir, as mesmas etapas são executadas em várias versões do Ubuntu Linux. (E não precisamos mencionar a jobs palavra-chave, já que há 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

Pontos finais

Os contêineres podem ser hospedados em registros diferentes dos registros públicos do Docker Hub. 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 ao registro privado. Em seguida, você pode fazer referência a ele em uma especificação de contêiner:

container:
  image: registry:ubuntu1804
  endpoint: private_dockerhub_connection

steps:
- script: echo hello

ou

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

steps:
- script: echo hello

Outros registos de contentores também podem funcionar. Atualmente, o Amazon ECR não funciona, pois há outras ferramentas de cliente necessárias para converter credenciais da AWS em algo que o Docker pode usar para autenticar.

Nota

A compilação do Red Hat Enterprise Linux 6 do agente não executará o trabalho de contêiner. Escolha outro tipo de Linux, como o Red Hat Enterprise Linux 7 ou superior.

Opções

Se você precisar controlar a inicialização do contêiner, poderá especificar options.

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

steps:
- script: echo hello

A execução docker create --help fornecerá a lista de opções que podem ser passadas para a chamada do Docker. Nem todas essas opções são garantidas para funcionar com o Azure DevOps. Verifique primeiro se você pode usar uma propriedade container para atingir o mesmo objetivo. Para obter mais informações, consulte resources.containers.container o esquema YAML e a referência de docker create comando .

Definição de recipiente reutilizável

No exemplo a seguir, os contêineres são definidos na seção de recursos. Cada contêiner é referenciado posteriormente, referindo-se ao seu alias atribuído. (Aqui, listamos explicitamente a jobs palavra-chave 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

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 é compilada em relação ao tempo de execução C que usamos em nossa 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 como um contêiner de trabalho, precisará organizar algumas coisas por conta própria. Primeiro, você deve fornecer sua própria cópia do Node.js. Em segundo lugar, você deve adicionar um rótulo à sua imagem informando ao agente onde encontrar o binário .js nó. Finalmente, o stock Alpine não vem com outras dependências das quais o Azure Pipelines depende: bash, sudo, which e groupadd.

Traga o seu próprio nó.js

Você é responsável por adicionar um binário de nó ao seu contêiner. O nó 14 é uma escolha segura. Você pode começar a partir da node:14-alpine imagem.

Informe o agente sobre o Node.js

O agente lerá um rótulo de contêiner "com.azure.dev.pipelines.handler.node.path". Se esse rótulo existir, ele deve ser o caminho para o binário Node.js. Por exemplo, em uma imagem baseada em node:10-alpine, adicione esta linha ao seu Dockerfile:

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

Adicionar requisitos

O Azure Pipelines assume um sistema baseado em Bash com pacotes de administração comuns instalados. O Alpine Linux, em particular, não vem com vários dos pacotes necessários. Instalando bash, sudo, e shadow cobrirá as necessidades básicas.

RUN apk add bash sudo shadow

Se você depender de qualquer tarefa da caixa de entrada ou do Marketplace, também precisará fornecer os binários necessários.

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

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

O trabalho de contêiner usa o agente de host subjacente Docker config.json para autorização de registro de imagem, que efetua logout no final da inicialização do contêiner de registro do Docker. A autorização de recebimento de imagem de registro subsequente pode ser negada para "autenticação não autorizada" porque o arquivo config.json do Docker registrado no sistema para autenticação já foi desconectado por um dos outros trabalhos de contêiner que estão sendo executados em paralelo.

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

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