doc-locale/fr-fr/ci/services/_index.md
{{< details >}}
{{< /details >}}
Lorsque vous configurez CI/CD, vous spécifiez une image, qui est utilisée pour créer le conteneur dans lequel vos jobs s'exécutent. Pour spécifier cette image, vous utilisez le mot-clé image.
Vous pouvez spécifier une image supplémentaire en utilisant le mot-clé services. Cette image supplémentaire est utilisée pour créer un autre conteneur, qui est accessible au premier conteneur. Les deux conteneurs ont accès l'un à l'autre et peuvent communiquer lors de l'exécution du job.
L'image de service peut exécuter n'importe quelle application, mais le cas d'utilisation le plus courant est d'exécuter un conteneur de base de données, par exemple :
[!warning] Pour activer la mise en réseau inter-services, définissez
FF_NETWORK_PER_BUILDsurtrue. Sans ce flag, les services peuvent ne pas fonctionner correctement. Pour plus d'informations, consultez les feature flags.
Supposons que vous développez un système de gestion de contenu qui utilise une base de données pour le stockage. Vous avez besoin d'une base de données pour tester toutes les fonctionnalités de l'application. Exécuter un conteneur de base de données comme image de service est un bon cas d'utilisation dans ce scénario.
Utilisez une image existante et exécutez-la comme conteneur supplémentaire plutôt que d'installer mysql à chaque fois que vous compilez un projet.
Vous n'êtes pas limité aux seuls services de base de données. Vous pouvez ajouter autant de services que nécessaire dans .gitlab-ci.yml ou modifier manuellement le config.toml. Toute image trouvée sur Docker Hub ou dans votre registre de conteneurs privé peut être utilisée comme service.
Pour plus d'informations sur l'utilisation d'images privées, consultez Accéder à une image depuis un registre de conteneurs privé.
Les services héritent des mêmes serveurs DNS, domaines de recherche et hôtes supplémentaires que le conteneur CI lui-même.
Pour mieux comprendre le fonctionnement de la liaison de conteneurs, consultez Linking containers together.
Si vous ajoutez mysql comme service à votre application, l'image est utilisée pour créer un conteneur lié au conteneur du job.
Le conteneur de service pour MySQL est accessible sous le nom d'hôte mysql. Pour accéder à votre service de base de données, connectez-vous à l'hôte nommé mysql plutôt qu'à un socket ou à localhost. Pour en savoir plus, consultez accéder aux services.
Les services sont conçus pour fournir des fonctionnalités supplémentaires network accessible. Il peut s'agir d'une base de données comme MySQL, ou Redis, et même de docker:dind qui vous permet d'utiliser Docker-in-Docker (DinD). Il peut s'agir pratiquement de n'importe quoi qui est requis pour que le job CI/CD se déroule, et qui est accessible via le réseau.
Pour s'assurer que cela fonctionne, le runner :
Si la deuxième étape du contrôle échoue, il affiche l'avertissement : *** WARNING: Service XYZ probably didn't start properly. Ce problème peut survenir pour les raisons suivantes :
Dans la plupart des cas, cela affecte le job, mais il peut arriver que le job réussisse quand même, même si cet avertissement a été affiché. Par exemple :
/builds). Dans ce cas, le service effectue son travail et, comme le job n'essaie pas de s'y connecter, il ne échoue pas.Si les services démarrent avec succès, ils démarrent avant l'exécution de before_script. Cela signifie que vous pouvez écrire un before_script qui interroge le service.
Les services s'arrêtent à la fin du job, même si le job échoue.
Lorsque vous spécifiez le service, cela fournit des services network accessible. Une base de données est l'exemple le plus simple d'un tel service.
La fonctionnalité de services n'ajoute aucun logiciel provenant des images services définies dans le conteneur du job.
Par exemple, si vous avez les services suivants définis dans votre job, les commandes php, node ou go ne sont pas disponibles pour votre script, et le job échoue :
job:
services:
- php:8.4
- node:latest
- golang:1.25
image: alpine:3.23
script:
- php -v
- node -v
- go version
Si vous avez besoin que php, node et go soient disponibles pour votre script, vous devez soit :
services dans le fichier .gitlab-ci.yml {#define-services-in-the-gitlab-ciyml-file}Il est également possible de définir différentes images et services par job :
default:
before_script:
- bundle install
test:4.0:
image: ruby:4.0
services:
- postgres:18
script:
- bundle exec rake spec
test:3.4:
image: ruby:3.4
services:
- postgres:17
script:
- bundle exec rake spec
Ou vous pouvez passer certaines options de configuration étendues pour image et services :
default:
image:
name: ruby:4.0
entrypoint: ["/bin/bash"]
services:
- name: my-postgres:18
alias: db,postgres,pg
entrypoint: ["/usr/local/bin/db-postgres"]
command: ["start"]
before_script:
- bundle install
test:
script:
- bundle exec rake spec
Si vous ne spécifiez pas d'alias de service, vous y avez accès depuis votre conteneur de compilation sous deux noms d'hôte :
namespace-projectnamenamespace__projectnameLes noms d'hôte contenant des underscores ne sont pas conformes à la RFC et peuvent causer des problèmes dans des applications tierces.
Les alias par défaut pour le nom d'hôte du service sont créés à partir du nom de son image en suivant ces règles :
:) est supprimé./) est remplacé par des doubles underscores (__) et l'alias principal est créé./) est remplacé par un tiret simple (-) et l'alias secondaire est créé.Pour remplacer le comportement par défaut, vous pouvez spécifier un ou plusieurs alias de service.
Vous pouvez utiliser des services interdépendants avec des jobs complexes, comme des tests de bout en bout où une API externe doit communiquer avec sa propre base de données.
Par exemple, pour un test de bout en bout d'une application front-end qui utilise une API, et où l'API a besoin d'une base de données :
end-to-end-tests:
image: node:latest
services:
- name: selenium/standalone-firefox:${FIREFOX_VERSION}
alias: firefox
- name: registry.gitlab.com/organization/private-api:latest
alias: backend-api
- name: postgres:18
alias: db postgres db
variables:
FF_NETWORK_PER_BUILD: 1 # activate container-to-container networking
POSTGRES_PASSWORD: supersecretpassword
BACKEND_POSTGRES_HOST: postgres
script:
- npm install
- npm test
Pour que cette solution fonctionne, vous devez utiliser le mode réseau qui crée un nouveau réseau pour chaque job.
Vous pouvez également transmettre des variables CI/CD personnalisées pour affiner vos images et services Docker directement dans le fichier .gitlab-ci.yml. Pour plus d'informations, consultez les variables définies dans .gitlab-ci.yml.
# The following variables are automatically passed down to the Postgres container
# as well as the Ruby container and available within each.
variables:
HTTPS_PROXY: "https://10.1.1.1:8090"
HTTP_PROXY: "https://10.1.1.1:8090"
POSTGRES_DB: "my_custom_db"
POSTGRES_USER: "postgres"
POSTGRES_PASSWORD: "example"
PGDATA: "/var/lib/postgresql/data"
POSTGRES_INITDB_ARGS: "--encoding=UTF8 --data-checksums"
default:
services:
- name: postgres:18
alias: db
entrypoint: ["docker-entrypoint.sh"]
command: ["postgres"]
image:
name: ruby:4.0
entrypoint: ["/bin/bash"]
before_script:
- bundle install
test:
script:
- bundle exec rake spec
services {#available-settings-for-services}Pour des informations détaillées sur les sous-clés de services:, consultez la référence YAML CI/CD.
Avant les nouvelles options de configuration Docker étendues, la configuration suivante ne fonctionnerait pas correctement :
services:
- mysql:latest
- mysql:latest
Le runner démarrerait deux conteneurs, chacun utilisant l'image mysql:latest. Cependant, les deux seraient ajoutés au conteneur du job avec l'alias mysql, en fonction de la dénomination des noms d'hôte par défaut. Cela aurait pour conséquence que l'un des services ne serait pas accessible.
Avec les nouvelles options de configuration Docker étendues, l'exemple précédent ressemblerait à ceci :
services:
- name: mysql:latest
alias: mysql-1
- name: mysql:latest
alias: mysql-2
Le runner démarre toujours deux conteneurs en utilisant l'image mysql:latest, mais désormais chacun d'eux est également accessible avec l'alias configuré dans le fichier .gitlab-ci.yml.
Supposons que vous disposez d'une image super/sql:latest contenant une base de données SQL. Vous souhaitez l'utiliser comme service pour votre job. Supposons également que cette image ne démarre pas le processus de base de données lors du démarrage du conteneur. L'utilisateur doit utiliser manuellement /usr/bin/super-sql run comme commande pour démarrer la base de données.
Avant les nouvelles options de configuration Docker étendues, vous deviez :
Créer votre propre image basée sur l'image super/sql:latest.
Ajouter la commande par défaut.
Utiliser l'image dans la configuration du job.
Dockerfile de l'image my-super-sql:latest :
FROM super/sql:latest
CMD ["/usr/bin/super-sql", "run"]
Dans le job dans le fichier .gitlab-ci.yml :
services:
- my-super-sql:latest
Avec les nouvelles options de configuration Docker étendues, vous pouvez définir une command dans le fichier .gitlab-ci.yml à la place :
services:
- name: super/sql:latest
command: ["/usr/bin/super-sql", "run"]
La syntaxe de command est similaire à celle de Dockerfile CMD.
{{< history >}}
{{< /history >}}
Vous pouvez utiliser des alias de service comme noms de conteneurs de service pour l'exécuteur Kubernetes. GitLab Runner nomme les conteneurs en fonction des conditions suivantes :
svc-i.Les exemples suivants illustrent la façon dont les alias sont utilisés pour nommer les conteneurs de service pour l'exécuteur Kubernetes.
Dans le fichier .gitlab-ci.yml suivant :
job:
image: alpine:latest
script:
- sleep 10
services:
- name: alpine:latest
alias: alpine
- name: mysql:latest
alias: mysql
Le système crée un Pod de job avec des conteneurs nommés alpine et mysql en plus des conteneurs standard build et helper. Ces alias sont utilisés car ils :
Cependant, dans le fichier .gitlab-ci.yml suivant :
job:
image: alpine:latest
script:
- sleep 10
services:
- name: mysql:lts
alias: mysql
- name: mysql:latest
alias: mysql
Le système crée deux conteneurs supplémentaires nommés mysql et svc-0 en plus des conteneurs build et helper. Le conteneur mysql correspond à l'image mysql:lts, tandis que le conteneur svc-0 correspond à l'image mysql:latest.
Dans le fichier .gitlab-ci.yml suivant :
job:
image: alpine:latest
script:
- sleep 10
services:
- name: alpine:latest
alias: alpine,alpine-latest
- name: alpine:edge
alias: alpine,alpine-edge,alpine-latest
Le système crée quatre conteneurs supplémentaires en plus des conteneurs build et helper :
alpine qui devrait correspondre au conteneur avec l'image alpine:latest.alpine-edge qui devrait correspondre au conteneur avec l'image alpine:edge (l'alias alpine étant déjà utilisé pour le conteneur précédent).Dans cet exemple, l'alias alpine-latest n'est pas utilisé.
Cependant, dans le fichier .gitlab-ci.yml suivant :
job:
image: alpine:latest
script:
- sleep 10
services:
- name: alpine:latest
alias: alpine,alpine-edge
- name: alpine:edge
alias: alpine,alpine-edge
- name: alpine:3.21
alias: alpine,alpine-edge
En plus des conteneurs build et helper, six autres conteneurs sont créés.
alpine devrait faire référence au conteneur avec l'image alpine:latest.
alpine-edge devrait faire référence au conteneur avec l'image alpine:edge (l'alias alpine étant déjà utilisé pour le conteneur précédent).
svc-0 devrait faire référence au conteneur avec l'image alpine:3.21 (les aliases alpine et alpine-edge étant déjà utilisés pour les conteneurs précédents).
Le i dans le modèle svc-i n'indique pas la position du service dans la liste fournie. Il représente plutôt la position du service lorsqu'aucun alias disponible n'est trouvé.
Lorsqu'un alias invalide est fourni (ne respectant pas les contraintes Kubernetes), le job échoue avec l'erreur suivante (exemple avec l'alias alpine_edge). Cet échec se produit car les aliases sont également utilisés pour créer des entrées DNS locales sur le Pod du job.
ERROR: Job failed (system failure): prepare environment: setting up build pod: provided host alias
alpine_edge for service alpine:edge is invalid DNS. a lowercase RFC 1123 subdomain must consist of lower
case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g.
'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*').
Check https://docs.gitlab.com/runner/shells/index/#shell-profile-loading for more information.
services avec docker run (Docker-in-Docker) côte à côte {#using-services-with-docker-run-docker-in-docker-side-by-side}Les conteneurs démarrés avec docker run peuvent également se connecter aux services fournis par GitLab.
Si le démarrage d'un service est coûteux ou prend du temps, vous pouvez exécuter des tests depuis différents environnements clients, tout en ne démarrant le service testé qu'une seule fois.
access-service:
stage: build
image: docker:20.10.16
services:
- docker:dind # necessary for docker run
- traefik/whoami:latest
variables:
FF_NETWORK_PER_BUILD: "true" # activate container-to-container networking
script: |
docker run --rm --name curl \
--volume "$(pwd)":"$(pwd)" \
--workdir "$(pwd)" \
--network=host \
curlimages/curl:latest curl "http://traefik-whoami"
Pour que cette solution fonctionne, vous devez :
host.Voici une vue d'ensemble de haut niveau des étapes effectuées par Docker lors de l'exécution d'un job.
mysql, postgresql, mongodb, redis.config.toml et Dockerfile de l'image de compilation (ruby:4.0 comme dans les exemples précédents)./builds/group-name/project-name/..gitlab-ci.yml.Les journaux générés par les applications s'exécutant dans des conteneurs de service peuvent être capturés pour un examen et un débogage ultérieurs. Consultez les journaux des conteneurs de service lorsqu'un conteneur de service démarre avec succès mais provoque des échecs de job en raison d'un comportement inattendu. Les journaux peuvent indiquer une configuration manquante ou incorrecte du service dans le conteneur.
CI_DEBUG_SERVICES ne doit être activé que lorsque les conteneurs de service font l'objet d'un débogage actif, car la capture des journaux des conteneurs de service a des conséquences sur le stockage et les performances.
[!warning] L'activation de
CI_DEBUG_SERVICESpeut révéler des variables masquées. LorsqueCI_DEBUG_SERVICESest activé, les journaux des conteneurs de service et les journaux du job CI sont diffusés simultanément dans le journal de trace du job. Cela signifie que les journaux des conteneurs de service peuvent être insérés dans un journal masqué du job. Cela contrecarrerait le mécanisme de masquage des variables et entraînerait la révélation de la variable masquée.
Pour activer la journalisation des services, ajoutez la variable CI/CD CI_DEBUG_SERVICES au fichier .gitlab-ci.yml du projet :
variables:
CI_DEBUG_SERVICES: "true"
Les valeurs acceptées sont :
TRUE, true, TrueFALSE, false, FalseToute autre valeur entraîne un message d'erreur et désactive effectivement la fonctionnalité.
Lorsqu'il est activé, les journaux de tous les conteneurs de service sont capturés et diffusés simultanément dans le journal de trace des jobs avec les autres journaux. Les journaux de chaque conteneur sont préfixés par les aliases du conteneur et affichés dans une couleur différente.
[!note] Pour diagnostiquer les échecs de job, vous pouvez ajuster le niveau de journalisation dans votre conteneur de service pour lequel vous souhaitez capturer des journaux. Le niveau de journalisation par défaut peut ne pas fournir suffisamment d'informations pour le dépannage.
Consultez Masquer une variable CI/CD
Les commandes suivantes sont exécutées sans privilèges root. Vérifiez que vous pouvez exécuter des commandes Docker avec votre compte utilisateur.
Commencez par créer un fichier nommé build_script :
cat <<EOF > build_script
git clone https://gitlab.com/gitlab-org/gitlab-runner.git /builds/gitlab-org/gitlab-runner
cd /builds/gitlab-org/gitlab-runner
make runner-bin-host
EOF
Cet exemple utilise le dépôt GitLab Runner qui contient un Makefile, de sorte que l'exécution de make exécute la cible définie dans le Makefile. Au lieu de make runner-bin-host, vous pouvez exécuter la commande spécifique à votre projet.
Créez ensuite un conteneur de service :
docker run -d --name service-redis redis:latest
La commande précédente crée un conteneur de service nommé service-redis en utilisant la dernière image Redis. Le conteneur de service s'exécute en arrière-plan (-d).
Enfin, créez un conteneur de compilation en exécutant le fichier build_script que vous avez créé précédemment :
docker run --name build -i --link=service-redis:redis golang:latest /bin/bash < build_script
La commande précédente crée un conteneur nommé build issu de l'image golang:latest et ayant un service lié à lui. Le build_script est transmis via stdin à l'interpréteur bash qui exécute à son tour le build_script dans le conteneur build.
Utilisez la commande suivante pour supprimer les conteneurs une fois les tests terminés :
docker rm -f -v build service-redis
Cette commande supprime de force (-f) le conteneur build, le conteneur de service et tous les volumes (-v) créés lors de la création du conteneur.
Le mode privilégié Docker s'applique aux services. Cela signifie que le conteneur de l'image de service peut accéder au système hôte. Vous devez utiliser uniquement des images de conteneurs provenant de sources fiables.
/builds partagé {#shared-builds-directory}Le répertoire de compilation est monté en tant que volume sous /builds et est partagé entre le job et les services. Le job extrait le projet dans /builds/$CI_PROJECT_PATH une fois les services en cours d'exécution. Votre service peut avoir besoin d'accéder aux fichiers du projet ou de stocker des artefacts. Si c'est le cas, attendez que le répertoire existe et que $CI_COMMIT_SHA soit extrait. Toute modification effectuée avant que le job termine son processus d'extraction est supprimée par le processus d'extraction.
Le service doit détecter quand le répertoire du job est rempli et prêt à être traité. Par exemple, attendez qu'un fichier spécifique soit disponible.
Les services qui commencent à fonctionner immédiatement après leur lancement risquent d'échouer, car les données du job peuvent ne pas encore être disponibles. Par exemple, les conteneurs utilisent la commande docker build pour établir une connexion réseau avec le service DinD. Le service demande à son API de démarrer la compilation d'une image de conteneur. Le Docker Engine doit avoir accès aux fichiers que vous référencez dans votre Dockerfile. Par conséquent, vous avez besoin d'accéder au CI_PROJECT_DIR dans le service. Cependant, Docker Engine n'essaie pas d'y accéder avant que la commande docker build soit appelée dans un job. À ce moment, le répertoire /builds est déjà rempli de données. Le service qui tente d'écrire dans CI_PROJECT_DIR immédiatement après son démarrage peut échouer avec une erreur No such file or directory.
Dans les scénarios où des services interagissant avec les données du job ne sont pas contrôlés par le job lui-même, consultez le workflow de l'exécuteur Docker.