Conteneurs de service
Azure DevOps Services
Si votre pipeline nécessite la prise en charge d’un ou plusieurs services, dans de nombreux cas, vous souhaiterez créer, connecter et nettoyer chaque service par travail. Par exemple, un pipeline peut exécuter des tests d’intégration qui nécessitent l’accès à une base de données et à un cache de mémoire. La base de données et le cache de mémoire doivent être nouvellement créés pour chaque travail dans le pipeline.
Un conteneur fournit un moyen simple et portable d’exécuter un service dont dépend votre pipeline. Un conteneur de service vous permet de créer, de mettre en réseau et de gérer automatiquement le cycle de vie de votre service conteneurisé. Chaque conteneur de service est accessible uniquement par le travail qui l’exige. Les conteneurs de service fonctionnent avec n’importe quel type de travail, mais ils sont le plus couramment utilisés avec les travaux de conteneur.
Configuration requise
Les conteneurs de service doivent définir un CMD
ou ENTRYPOINT
.
Le pipeline s’exécute docker run
pour le conteneur fourni sans arguments supplémentaires.
Azure Pipelines peut exécuter des conteneurs Linux ou Windows. Utilisez des conteneurs Ubuntu pour Linux hébergés ou le pool de conteneurs Windows hébergé pour les conteneurs Windows. (Le pool macOS hébergé ne prend pas en charge l’exécution de conteneurs.)
Travail de conteneur unique
Exemple simple d’utilisation de travaux de conteneur :
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
Ce pipeline extrait les conteneurs nginx
et buildpack-deps
à partir de Docker Hub, puis démarre les conteneurs. Les conteneurs sont mis en réseau ensemble afin qu’ils puissent se joindre les uns aux autres par leur nom services
.
À partir de ce conteneur de travaux, le nom d’hôte nginx
est résolu en services appropriés à l’aide de la mise en réseau Docker.
Tous les conteneurs du réseau exposent automatiquement tous les ports les uns aux autres.
Travail unique
Vous pouvez également utiliser des conteneurs de service sans conteneur de travaux. Voici un exemple simple :
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
Ce pipeline démarre les derniers conteneurs nginx
. Étant donné que le travail n’est pas en cours d’exécution dans un conteneur, il n’y a pas de résolution automatique de noms.
Cet exemple montre comment atteindre les services à l’aide de localhost
.
Dans l’exemple ci-dessus, nous fournissons le port explicitement (par exemple, 8080:80
).
Une autre approche consiste à laisser un port aléatoire être affecté dynamiquement au moment de l’exécution. Vous pouvez ensuite accéder à ces ports dynamiques à l’aide de variables.
Dans un script Bash, vous pouvez accéder à une variable à l’aide de l’environnement de processus. Ces variables prennent la forme suivante : agent.services.<serviceName>.ports.<port>
.
Dans l’exemple ci-dessus, redis
reçoit un port disponible aléatoire sur l’hôte.
La variable agent.services.redis.ports.6379
contient le numéro de port.
Plusieurs travaux
Les conteneurs de service sont également utiles pour exécuter les mêmes étapes sur plusieurs versions du même service. Dans l’exemple suivant, les mêmes étapes s’exécutent sur plusieurs versions de 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
Ports
Lorsque vous spécifiez une ressource de conteneur ou un conteneur inline, vous pouvez spécifier un tableau de ports
à exposer sur le conteneur.
resources:
containers:
- container: my_service
image: my_service:latest
ports:
- 8080:80
- 5432
services:
redis:
image: redis
ports:
- 6379/tcp
La spécification ports
n’est pas obligatoire si votre travail s’exécute dans un conteneur, car les conteneurs sur le même réseau Docker exposent automatiquement tous les ports les uns aux autres par défaut.
Si votre travail s’exécute sur l’hôte, ports
vous devez accéder au service. Un port prend la forme <hostPort>:<containerPort>
ou simplement <containerPort>
, avec un facultatif /<protocol>
à la fin, par exemple 6379/tcp
pour exposer tcp
sur le port 6379
, lié à un port aléatoire sur l’ordinateur hôte.
Pour les ports liés à un port aléatoire sur l’ordinateur hôte, le pipeline crée une variable du formulaire agent.services.<serviceName>.ports.<port>
afin que le travail puisse y accéder. Par exemple, agent.services.redis.ports.6379
résout le port attribué de manière aléatoire sur l’ordinateur hôte.
Volumes
Les volumes sont utiles pour partager des données entre services ou pour conserver des données entre plusieurs exécutions d’un travail.
Vous pouvez spécifier des montages de volumes en tant que tableau de volumes
. Les volumes peuvent être nommés volumes Docker, volumes Docker anonymes ou montages de liaison sur l’hôte.
services:
my_service:
image: myservice:latest
volumes:
- mydockervolume:/data/dir
- /data/dir
- /src/dir:/dst/dir
Les volumes prennent la forme <source>:<destinationPath>
, où <source>
peut être un volume nommé ou un chemin absolu sur l’ordinateur hôte, et <destinationPath>
est un chemin d’accès absolu dans le conteneur.
Notes
Si vous utilisez nos pools hébergés, vos volumes ne seront pas conservés entre les travaux, car l’ordinateur hôte est nettoyé une fois le travail terminé.
Autres options
Les conteneurs de service partagent les mêmes ressources de conteneur que les travaux de conteneur. Cela signifie que vous pouvez utiliser les mêmes options supplémentaires.
Healthcheck
Si vous le souhaitez, si un conteneur de service spécifie un HEALTHCHECK, l’agent attend que le conteneur soit sain avant d’exécuter le travail.
Exemple de plusieurs conteneurs avec services
Dans cet exemple, il existe un conteneur web Python Django connecté à deux conteneurs de base de données : PostgreSQL et MySQL. La base de données PostgreSQL est la base de données primaire et son conteneur porte le nom db
. Le conteneur db
utilise des /data/db:/var/lib/postgresql/data
de volume et il existe trois variables de base de données transmises au conteneur via env
. Le conteneur mysql
utilise le port 3306:3306
et il existe également des variables de base de données passées via env
. Le conteneur web
est ouvert avec le port 8000
. Dans les étapes, pip
installe les dépendances, puis le test Django est exécuté. Si vous souhaitez obtenir un exemple de configuration de travail, vous aurez besoin d’un site Django configuré avec deux bases de données. Cet exemple suppose que votre fichier manage.py
se trouve dans le répertoire racine et que votre projet Django se trouve dans ce répertoire. Vous devrez peut-être mettre à jour le chemin d’accès /__w/1/s/
dans /__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
Commentaires
https://aka.ms/ContentUserFeedback.
Bientôt disponible : Tout au long de 2024, nous allons supprimer progressivement GitHub Issues comme mécanisme de commentaires pour le contenu et le remplacer par un nouveau système de commentaires. Pour plus d’informations, consultezEnvoyer et afficher des commentaires pour