Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Serviços do Azure DevOps
Este artigo descreve o uso de contêineres de serviço no Azure Pipelines. Se o pipeline exigir o suporte de um ou mais serviços, talvez seja necessário criar, conectar e limpar os serviços para cada tarefa. Por exemplo, seu pipeline pode executar testes de integração que exigem acesso a um banco de dados recém-criado e cache de memória para cada trabalho no pipeline.
Um contêiner de serviço fornece uma maneira simples e portátil de executar serviços em seu pipeline. O contêiner de serviço só pode ser acessado para o trabalho que o requer.
Os contêineres de serviço permitem que você crie, rede e gerencie automaticamente os ciclos de vida dos serviços dos quais seus pipelines dependem. Os contêineres de serviço funcionam com qualquer tipo de trabalho, mas são mais comumente usados com trabalhos de contêiner.
Observação
Pipelines clássicos não dão suporte para contêineres de serviços.
Condições e limitações
Os contêineres de serviço precisam definir um
CMDouENTRYPOINT. O pipeline é executadodocker runsem argumentos para o contêiner fornecido.O Azure Pipelines pode executar contêineres do Linux ou do Windows . Você usa o pool do Ubuntu hospedado para contêineres do Linux ou o pool do Windows hospedado para contêineres do Windows. O pool do macOS hospedado não dá suporte à execução de contêineres.
Os contêineres de serviço compartilham os mesmos recursos de contêiner que os trabalhos de contêiner, para que possam usar as mesmas opções de inicialização.
Se um contêiner de serviço especificar um HEALTHCHECK, o agente tem a opção de esperar até que o contêiner esteja em boas condições antes de executar o trabalho.
Trabalho de contêiner único
O pipeline YAML de exemplo a seguir define um único trabalho de contêiner que usa um contêiner de serviço. O pipeline busca os contêineres buildpack-deps e nginx do Hub do Docker e, em seguida, inicia todos os contêineres. Os contêineres são em rede para que possam alcançar uns aos outros por seus services nomes.
De dentro do contêiner do trabalho, o nome do nginx host é resolvido para os serviços corretos usando a rede do Docker. Todos os contêineres na rede expõem automaticamente todas as portas uns para os outros.
resources:
containers:
- container: my_container
image: buildpack-deps:focal
- container: nginx
image: nginx
pool:
vmImage: 'ubuntu-latest'
container: my_container
services:
nginx: nginx
steps:
- script: |
curl nginx
displayName: Show that nginx is running
Trabalho único que não é contêiner
Você também pode usar contêineres de serviço em trabalhos fora de contêiner. O pipeline inicia os últimos contêineres, mas como o trabalho não é executado em um contêiner, não ocorre resolução automática de nomes. Em vez disso, você chega aos serviços usando localhost. O seguinte exemplo de pipeline especifica explicitamente a porta 8080:80 para nginx.
Uma abordagem alternativa é atribuir uma porta aleatória dinamicamente em runtime. Para permitir que o trabalho acesse a porta, o pipeline cria uma variável no formato agent.services.<serviceName>.ports.<port>. Você pode acessar a porta dinâmica usando essa variável de ambiente em um script Bash.
No pipeline a seguir, redis obtém uma porta disponível aleatória no host e a agent.services.redis.ports.6379 variável contém o número da porta.
resources:
containers:
- container: nginx
image: nginx
ports:
- 8080:80
env:
NGINX_PORT: 80
- container: redis
image: redis
ports:
- 6379
pool:
vmImage: 'ubuntu-latest'
services:
nginx: nginx
redis: redis
steps:
- script: |
curl localhost:8080
echo $AGENT_SERVICES_REDIS_PORTS_6379
Vários trabalhos
Os contêineres de serviço também são úteis para executar as mesmas etapas em várias versões do mesmo serviço. No exemplo a seguir, as mesmas etapas são executadas em várias versões do PostgreSQL.
resources:
containers:
- container: my_container
image: ubuntu:22.04
- container: pg15
image: postgres:15
- container: pg14
image: postgres:14
pool:
vmImage: 'ubuntu-latest'
strategy:
matrix:
postgres15:
postgresService: pg15
postgres14:
postgresService: pg14
container: my_container
services:
postgres: $[ variables['postgresService'] ]
steps:
- script: printenv
Portas
Trabalhos executados diretamente no host exigem ports para acessar o contêiner de serviço. A especificação ports não será necessária se o trabalho for executado em um contêiner, pois os contêineres na mesma rede do Docker expõem automaticamente todas as portas entre si por padrão.
Uma porta assume a forma <hostPort>:<containerPort> ou apenas <containerPort> com um opcional /<protocol> no final. Por exemplo, 6379/tcp expõe tcp a porta 6379, vinculada a uma porta aleatória na máquina host.
Ao invocar um recurso de contêiner ou um contêiner embutido, você pode especificar uma matriz para ports expor no contêiner, como no exemplo a seguir.
resources:
containers:
- container: my_service
image: my_service:latest
ports:
- 8080:80
- 5432
services:
redis:
image: redis
ports:
- 6379/tcp
Para portas associadas a uma porta aleatória na máquina host, o pipeline cria uma variável do formulário agent.services.<serviceName>.ports.<port> para que o trabalho possa acessar a porta. Por exemplo, agent.services.redis.ports.6379 resolve para a porta atribuída aleatoriamente no computador host.
Volumes
Os volumes são úteis para compartilhar dados entre serviços ou para persistir dados entre várias execuções de um trabalho. Você especifica as montagens de volume como uma matriz de volumes.
Cada volume assume o formulário <source>:<destinationPath>, onde <source> é um volume nomeado ou um caminho absoluto no host e <destinationPath> é um caminho absoluto no contêiner. Os volumes podem ser nomeados volumes do Docker, volumes anônimos do Docker ou montagens de associação no host.
services:
my_service:
image: myservice:latest
volumes:
- mydockervolume:/data/dir
- /data/dir
- /src/dir:/dst/dir
Observação
Os pools gerenciados pela Microsoft não mantêm volumes entre trabalhos, pois a máquina host é limpa após cada trabalho.
Exemplo de vários contêineres com serviços
O pipeline de exemplo a seguir tem um contêiner web do Python do Django conectado aos contêineres de banco de dados PostgreSQL e MySQL.
- O banco de dados PostgreSQL é o banco de dados primário e seu contêiner é denominado
db. - O
dbcontêiner usa volume/data/db:/var/lib/postgresql/datae passa três variáveis de banco de dados para o contêiner por meio deenv. - O
mysqlcontêiner usa a porta3306:3306e também passa variáveis de banco de dados por meio deenv. - O contêiner
webestá aberto com a porta8000.
Nas etapas, pip instala as dependências e, em seguida, os testes do Django são executados.
Para configurar um exemplo de trabalho, você precisa de um site Django configurado com dois bancos de dados. O exemplo pressupõe que seu arquivo manage.py e seu projeto do Django estejam no diretório raiz. Caso contrário, talvez seja necessário atualizar o /__w/1/s/ caminho no /__w/1/s/manage.py test.
resources:
containers:
- container: db
image: postgres
volumes:
- '/data/db:/var/lib/postgresql/data'
env:
POSTGRES_DB: postgres
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
- container: mysql
image: 'mysql:5.7'
ports:
- '3306:3306'
env:
MYSQL_DATABASE: users
MYSQL_USER: mysql
MYSQL_PASSWORD: mysql
MYSQL_ROOT_PASSWORD: mysql
- container: web
image: python
volumes:
- '/code'
ports:
- '8000:8000'
pool:
vmImage: 'ubuntu-latest'
container: web
services:
db: db
mysql: mysql
steps:
- script: |
pip install django
pip install psycopg2
pip install mysqlclient
displayName: set up django
- script: |
python /__w/1/s/manage.py test