Contenitori del servizio
Azure DevOps Services
Se la pipeline richiede il supporto di uno o più servizi, in molti casi si vuole creare, connettersi e pulire ogni servizio in base al processo. Ad esempio, una pipeline può eseguire test di integrazione che richiedono l'accesso a un database e a una cache di memoria. Per ogni processo nella pipeline è necessario creare il database e la cache di memoria.
Un contenitore offre un modo semplice e portabile per eseguire un servizio da cui dipende la pipeline. Un contenitore di servizi consente di creare, collegare in rete e gestire automaticamente il ciclo di vita del servizio in contenitori. Ogni contenitore di servizi è accessibile solo dal processo che lo richiede. I contenitori di servizi funzionano con qualsiasi tipo di processo, ma vengono usati più comunemente con i processi contenitore.
Requisiti
I contenitori di servizio devono definire un oggetto CMD
o ENTRYPOINT
.
La pipeline verrà eseguita docker run
per il contenitore fornito senza argomenti aggiuntivi.
Azure Pipelines può eseguire contenitori Linux o Windows. Usare Ubuntu ospitato per i contenitori Linux o il pool Di contenitori Windows ospitati per i contenitori Windows. Il pool macOS ospitato non supporta i contenitori in esecuzione.
Processo contenitore singolo
Esempio semplice di uso dei processi contenitore:
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
Questa pipeline recupera i nginx
contenitori e buildpack-deps
da Docker Hub e quindi avvia i contenitori. I contenitori vengono collegati insieme in modo che possano raggiungere l'uno dall'altro con il loro services
nome.
Dall'interno di questo contenitore di processi, il nginx
nome host si risolve nei servizi corretti usando la rete Docker.
Tutti i contenitori nella rete espongono automaticamente tutte le porte tra loro.
Processo singolo
È anche possibile usare i contenitori di servizio senza un contenitore di processi. Un semplice esempio:
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
Questa pipeline avvia i contenitori più recenti nginx
. Poiché il processo non è in esecuzione in un contenitore, non esiste una risoluzione automatica dei nomi.
In questo esempio viene illustrato come raggiungere i servizi usando localhost
.
Nell'esempio precedente viene specificata in modo esplicito la porta , ad esempio 8080:80
.
Un approccio alternativo consiste nell'consentire l'assegnazione dinamica di una porta casuale in fase di esecuzione. È quindi possibile accedere a queste porte dinamiche usando le variabili.
In uno script Bash è possibile accedere a una variabile usando l'ambiente di elaborazione. Queste variabili prendono il formato: agent.services.<serviceName>.ports.<port>
.
Nell'esempio precedente viene redis
assegnata una porta disponibile casuale nell'host.
La agent.services.redis.ports.6379
variabile contiene il numero di porta.
Più processi
I contenitori di servizi sono utili anche per eseguire gli stessi passaggi rispetto a più versioni dello stesso servizio. Nell'esempio seguente vengono eseguiti gli stessi passaggi su più versioni di 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
Porte
Quando si specifica una risorsa contenitore o un contenitore inline, è possibile specificare una matrice di da ports
esporre nel contenitore.
resources:
containers:
- container: my_service
image: my_service:latest
ports:
- 8080:80
- 5432
services:
redis:
image: redis
ports:
- 6379/tcp
ports
Se il processo è in esecuzione in un contenitore, la specifica non è necessaria perché i contenitori nella stessa rete Docker espongono automaticamente tutte le porte tra loro per impostazione predefinita.
Se il processo è in esecuzione nell'host, ports
è necessario accedere al servizio. Una porta accetta la forma <hostPort>:<containerPort>
o semplicemente <containerPort>
, con un facoltativo /<protocol>
alla fine, ad esempio 6379/tcp
per esporre tcp
sulla porta 6379
, associata a una porta casuale nel computer host.
Per le porte associate a una porta casuale nel computer host, la pipeline crea una variabile del modulo agent.services.<serviceName>.ports.<port>
in modo che possa essere accessibile dal processo. Ad esempio, agent.services.redis.ports.6379
risolve la porta assegnata in modo casuale nel computer host.
Volumi
I volumi sono utili per condividere i dati tra i servizi o per rendere persistenti i dati tra più esecuzioni di un processo.
È possibile specificare i montaggi del volume come matrice di volumes
. I volumi possono essere denominati volumi Docker, volumi Docker anonimi o montaggi di associazione nell'host.
services:
my_service:
image: myservice:latest
volumes:
- mydockervolume:/data/dir
- /data/dir
- /src/dir:/dst/dir
I volumi accettano il formato <source>:<destinationPath>
, dove <source>
può essere un volume denominato o un percorso assoluto nel computer host ed <destinationPath>
è un percorso assoluto nel contenitore.
Nota
Se si usano i pool ospitati, i volumi non verranno mantenuti tra processi perché il computer host viene pulito dopo il completamento del processo.
Altre opzioni
I contenitori di servizio condividono le stesse risorse del contenitore dei processi del contenitore. Ciò significa che è possibile usare le stesse opzioni aggiuntive.
Controllo integrità
Facoltativamente, se qualsiasi contenitore di servizio specifica un healthCHECK, l'agente attende fino a quando il contenitore non è integro prima di eseguire il processo.
Più contenitori con un esempio di servizi
In questo esempio è presente un contenitore Web Python Django connesso a due contenitori di database, PostgreSQL e MySQL. Il database PostgreSQL è il database primario e il relativo contenitore ha il nome db
. Il db
contenitore usa il volume /data/db:/var/lib/postgresql/data
e sono presenti tre variabili di database passate al contenitore tramite env
. Il mysql
contenitore usa la porta 3306:3306
e sono presenti anche variabili di database passate tramite env
. Il web
contenitore è aperto con la porta 8000
. Nei passaggi vengono pip
installate le dipendenze e quindi vengono eseguiti test Django. Se si vuole ottenere un esempio di lavoro configurato, è necessario configurare un sito Django con due database. In questo esempio si presuppone che il manage.py
file si trova nella directory radice e che il progetto Django si trova all'interno di tale directory. Potrebbe essere necessario aggiornare il /__w/1/s/
percorso in /__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
Commenti e suggerimenti
https://aka.ms/ContentUserFeedback.
Presto disponibile: Nel corso del 2024 verranno gradualmente disattivati i problemi di GitHub come meccanismo di feedback per il contenuto e ciò verrà sostituito con un nuovo sistema di feedback. Per altre informazioni, vedereInvia e visualizza il feedback per