web-dev-qa-db-fra.com

Utilisation de docker-compose avec CI - comment gérer les codes de sortie et les conteneurs liés démonisés?

Actuellement, nos agents Jenkins génèrent un fichier docker-compose.yml pour chacun de nos Rails), puis exécutent docker-compose up. Le fichier docker-compose.yml a un conteneur "Web" principal qui a rbenv et toutes nos autres dépendances Rails à l'intérieur. Il est lié à un conteneur de base de données contenant la base de données test Postgres.

Le problème survient lorsque nous devons réellement exécuter les tests et générer des codes de sortie. Notre serveur d'infrastructure ne se déploiera que si le script de test renvoie l'exit 0, mais docker-compose renvoie toujours 0, même si l'une des commandes de conteneur échoue.

L'autre problème est que le conteneur de base de données s'exécute indéfiniment, même après que le conteneur Web ait terminé l'exécution des tests, donc docker-compose up ne revient jamais.

Existe-t-il un moyen d'utiliser Docker-Compose pour ce processus? Nous devrions pouvoir exécuter les conteneurs, mais quitter une fois le conteneur Web terminé et renvoyer son code de sortie. Pour le moment, nous sommes bloqués manuellement à l'aide de docker pour faire tourner le conteneur de base de données et exécuter le conteneur Web avec l'option --link.

74
Logan Serman

Depuis la version 1.12.0, vous pouvez utiliser le --exit-code-from option.

De documentation :

--exit-code-from SERVICE

Renvoie le code de sortie du conteneur de service sélectionné. Implique --abort-on-container-exit.

64
panjan

docker-compose run est le moyen simple d’obtenir les statuts de sortie que vous désirez. Par exemple:

$ cat docker-compose.yml 
roit:
    image: busybox
    command: 'true'
naw:
    image: busybox
    command: 'false'
$ docker-compose run --rm roit; echo $?
Removing test_roit_run_1...
0
$ docker-compose run --rm naw; echo $?
Removing test_naw_run_1...
1

Alternativement, vous avez la possibilité de inspecter les conteneurs morts. Vous pouvez utiliser le -f drapeau pour obtenir uniquement le statut de sortie.

$ docker-compose up
Creating test_naw_1...
Creating test_roit_1...
Attaching to test_roit_1
test_roit_1 exited with code 0
Gracefully stopping... (press Ctrl+C again to force)
$ docker-compose ps -q | xargs docker inspect -f '{{ .Name }} exited with status {{ .State.ExitCode }}'
/test_naw_1 exited with status 1
/test_roit_1 exited with status 0

En ce qui concerne le conteneur de base de données qui ne retourne jamais, si vous utilisez docker-compose up alors vous aurez besoin de sigkill ce conteneur; ce n'est probablement pas ce que vous voulez. Au lieu de cela, vous pouvez utiliser docker-compose up -d pour exécuter vos conteneurs démonisés et les supprimer manuellement une fois votre test terminé. docker-compose run devrait exécuter des conteneurs liés pour vous, mais j'ai entendu des discussions sur SO) à propos d'un bogue empêchant son bon fonctionnement comme prévu en ce moment.

35
kojiro

S'appuyant sur la réponse de kojiro:

docker-compose ps -q | xargs docker inspect -f '{{ .State.ExitCode }}' | grep -v '^0' | wc -l | tr -d ' '

  1. obtenir les identifiants de conteneur
  2. obtenir les dernières exécutions du code de sortie pour chaque ID de conteneur
  3. seulement les codes d'état qui ne commencent pas par '0'
  4. compte le nombre de codes d'état non-0
  5. réduire l'espace blanc

Retourne combien de codes de sortie non-0 ont été retournés. Serait 0 si tout est sorti avec le code 0.

22
spenthil

Si vous êtes prêt à utiliser docker-compose run pour lancer manuellement vos tests, en ajoutant le --rm drapeau, curieusement, force Compose à refléter avec précision le statut de sortie de votre commande.

Voici mon exemple:

$ docker-compose -v
docker-compose version 1.7.0, build 0d7bf73

$ (docker-compose run kpi false) || echo 'Test failed!'  # False negative.

$ (docker-compose run --rm kpi false) || echo 'Test failed!'  # True positive.
Test failed!

$ (docker-compose run --rm kpi true) || echo 'Test failed!'  # True negative.
6
esmail

Utilisation docker wait pour obtenir le code de sortie:

$ docker-compose -p foo up -d
$ ret=$(docker wait foo_bar_1)

foo est le "nom du projet". Dans l'exemple ci-dessus, je l'ai spécifié explicitement, mais si vous ne le fournissez pas, c'est le nom du répertoire. bar est le nom que vous donnez au système testé dans votre fichier docker-compose.yml.

Notez que docker logs -f fait la bonne chose aussi, sortir quand le conteneur s'arrête. Donc tu peux mettre

$ docker logs -f foo_bar_1

entre le docker-compose up et le docker wait afin que vous puissiez regarder vos tests se dérouler.

6
Bryan Larsen

--exit-code-from SERVICE et --abort-on-container-exit ne fonctionne pas dans les scénarios dans lesquels vous devez exécuter tous les conteneurs, mais échouez si l’un d’eux s’est arrêté tôt. Un exemple pourrait être si vous exécutez 2 combinaisons de test simultanément dans des conteneurs différents.

Avec la suggestion de @USSHILH, vous pouvez envelopper docker-compose dans un script qui échouera si des conteneurs le font.

#!/bin/bash
set -e

# Wrap docker-compose and return a non-zero exit code if any containers failed.

docker-compose "$@"

exit $(docker-compose -f docker-compose.ci.build.yml ps -q | tr -d '[:space:]' |
  xargs docker inspect -f '{{ .State.ExitCode }}' | grep -v 0 | wc -l | tr -d '[:space:]')

Ensuite, sur votre serveur CI, changez simplement docker-compose up à ./docker-compose.sh up.

5
Matt Cole

Vous pouvez voir le statut exist avec:

echo $(docker-compose ps | grep "servicename" | awk '{print $4}')
2
RT Bathula

docker-Rails vous permet de spécifier le code d'erreur du conteneur renvoyé au processus principal afin que votre serveur CI puisse déterminer le résultat. C'est une excellente solution pour CI et le développement de Rails avec docker.

Par exemple

exit_code: web

dans votre docker-Rails.yml donnera le code de sortie des conteneurs web à la suite de la commande docker-Rails ci test. docker-Rails.yml est juste une méta-enveloppe autour de la norme docker-compose.yml qui vous donne le potentiel d’hériter/de réutiliser la même configuration de base pour différents environnements, c’est-à-dire développement vs test vs parallèle_tests.

1
kross

Dans le cas où vous pourriez exécuter plus de services de composition de docker avec le même nom sur un moteur de docker et dont vous ne connaissez pas le nom exact:

docker-compose up -d
(exit "${$(docker-compose logs -f test-chrome)##* }")

echo %? - renvoie le code de sortie du service test-chrome

Avantages:

  • attendre le service exact pour sortir
  • utilise le nom du service, pas le nom du conteneur
0
cvakiitho