J'utilise rabbitmq et un simple échantillon de python d' ici avec docker-compose. Mon problème est que je dois attendre que rabbitmq démarre complètement. D'après ce que j'ai cherché jusqu'à présent, je ne sais pas comment attendre avec le conteneur x (dans mon assistant social) jusqu'à ce que y (rabbitmq) soit démarré.
J'ai trouvé ce blog où il vérifie si l'autre hôte est en ligne. J'ai également trouvé cette commande docker :
attendre
Utilisation: docker wait CONTAINER [CONTAINER ...]
Bloquer jusqu'à l'arrêt d'un conteneur, puis imprimer son code de sortie.
Attendre l'arrêt d'un conteneur n'est peut-être pas ce que je recherche, mais si c'est le cas, est-il possible d'utiliser cette commande dans le docker-compose.yml? Jusqu'à présent, ma solution est d'attendre quelques secondes et de vérifier le port, mais est-ce le moyen d'y parvenir?. Si je n'attends pas, j'obtiens une erreur.
docker-compose.yml
worker:
build: myapp/.
volumes:
- myapp/.:/usr/src/app:ro
links:
- rabbitmq
rabbitmq:
image: rabbitmq:3-management
échantillon de python hello (rabbit.py):
import pika
import time
import socket
pingcounter = 0
isreachable = False
while isreachable is False and pingcounter < 5:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect(('rabbitmq', 5672))
isreachable = True
except socket.error as e:
time.sleep(2)
pingcounter += 1
s.close()
if isreachable:
connection = pika.BlockingConnection(pika.ConnectionParameters(
host="rabbitmq"))
channel = connection.channel()
channel.queue_declare(queue='hello')
channel.basic_publish(exchange='',
routing_key='hello',
body='Hello World!')
print (" [x] Sent 'Hello World!'")
connection.close()
Dockerfile pour le travailleur:
FROM python:2-onbuild
RUN ["pip", "install", "pika"]
CMD ["python","rabbit.py"]
Mise à jour de novembre 2015 :
Un script shell ou une attente dans votre programme est peut-être une solution possible. Mais après avoir vu ce problème, je recherche une commande ou une fonctionnalité de docker / docker-compose.
Ils mentionnent une solution pour mettre en place un bilan de santé, qui peut être la meilleure option. Une connexion TCP ouverte ne signifie pas que votre service est prêt ou peut rester prêt. En plus de cela, je dois changer mon point d'entrée dans mon dockerfile.
J'espère donc une réponse avec les commandes embarquées de docker-compose, ce qui sera le cas, espérons-le, si elles finissent ce problème.
Mise à jour mars 2016
Il est proposé de fournir une méthode intégrée pour déterminer si un conteneur est "vivant". Ainsi, docker-compose peut peut-être l'utiliser dans un avenir proche.
Mise à jour juin 2016
Il semble que le bilan de santé sera intégré dans docker dans la version 1.12.0
Mise à jour janvier 2017
J'ai trouvé une solution docker-compose voir: Docker Compose attendre le conteneur X avant de commencer Y
la source
Réponses:
Enfin trouvé une solution avec une méthode docker-compose. Depuis le format de fichier docker-compose 2.1, vous pouvez définir des contrôles de santé .
Je l'ai fait dans un exemple de projet dont vous avez besoin d'installer au moins docker 1.12.0+. J'ai également dû étendre le fichier Dockerfile de rabbitmq-management , car curl n'est pas installé sur l'image officielle.
Maintenant, je teste si la page de gestion du rabbitmq-container est disponible. Si curl se termine avec exitcode 0, l'application conteneur (python pika) sera démarrée et publiera un message dans la file d'attente hello. Son fonctionne maintenant (sortie).
docker-compose (version 2.1):
production:
Dockerfile (rabbitmq + curl):
La version 3 ne prend plus en charge la forme condition de depend_on . J'ai donc déménagé de depend_on pour redémarrer en cas d'échec. Maintenant, mon conteneur d'application va redémarrer 2-3 fois jusqu'à ce qu'il fonctionne, mais c'est toujours une fonctionnalité de composition de docker sans écraser le point d'entrée.
docker-compose (version 3):
la source
ping
utilise ICMP et ne prend donc pas en charge les ports TCP. Peut-êtrenc
pour tester un port TCP. Il vaut probablement mieux utiliserpsql -h localhost -p 5432
et interroger quelque chose.condition
forme dedepends_on
soit supprimée, maisdepends_on
elle-même est toujours présente dans la v3depends_on
aveccondition
a été supprimé?Nativement, ce n'est pas encore possible. Voir aussi cette demande de fonctionnalité .
Jusqu'à présent, vous devez le faire dans vos conteneurs
CMD
pour attendre que tous les services requis soient là.Dans le
Dockerfile
s,CMD
vous pouvez vous référer à votre propre script de démarrage qui termine le démarrage de votre service de conteneur. Avant de le démarrer, vous attendez un dépendant comme:Dockerfile
start.sh
Vous devrez probablement également installer netcat sur votre ordinateur
Dockerfile
. Je ne sais pas ce qui est pré-installé sur l'image python.Il existe quelques outils qui fournissent une logique d'attente facile à utiliser, pour des vérifications de port TCP simples:
Pour les attentes plus complexes:
la source
L'utilisation
restart: unless-stopped
ourestart: always
peut résoudre ce problème.Si le travailleur
container
s'arrête lorsque rabbitMQ n'est pas prêt, il sera redémarré jusqu'à ce qu'il le soit.la source
Tout récemment, ils ont ajouté la
depends_on
fonctionnalité .Éditer:
À partir de la version 2.1+ de compose, vous pouvez utiliser
depends_on
conjointement avechealthcheck
pour y parvenir:De la documentation :
Avant la version 2.1
Vous pouvez toujours l'utiliser
depends_on
, mais cela n'affecte que l' ordre dans lequel les services sont démarrés - pas s'ils sont prêts avant le démarrage du service dépendant.Il semble nécessiter au moins la version 1.6.0.
L'utilisation ressemblerait à quelque chose comme ceci:
De la documentation:
Remarque: Si je comprends bien, bien que cela définisse l'ordre dans lequel les conteneurs sont chargés. Il ne garantit pas que le service à l'intérieur du conteneur a effectivement été chargé.
Par exemple, votre conteneur postgres peut être actif. Mais le service postgres lui-même peut encore être en cours d'initialisation dans le conteneur.
la source
depends_on
." docs.docker.com/compose/compose-file/#dependsondepends_on
n'attend pas que le conteneur soit enready
état (quoi que cela puisse signifier dans votre cas). Il attend uniquement que le conteneur soit en état de «fonctionnement».vous pouvez également l'ajouter à l'option de commande, par exemple.
https://github.com/docker/compose/issues/374#issuecomment-156546513
d'attendre sur un port, vous pouvez également utiliser quelque chose comme ça
pour augmenter le temps d'attente, vous pouvez pirater un peu plus:
la source
restart: on-failure
a fait l'affaire pour moi..voir ci-dessousla source
Pour la commande de début de conteneur, utilisez
Pour attendre le script de démarrage du conteneur précédent
Cet article vous aidera https://docs.docker.com/compose/startup-order/
la source
Vous pouvez également résoudre ce problème en définissant un point de terminaison qui attend que le service soit opérationnel à l'aide de netcat (à l'aide du script docker-wait ). J'aime cette approche car vous avez toujours une
command
section propre dans votredocker-compose.yml
et vous n'avez pas besoin d'ajouter du code spécifique de docker à votre application:Alors votre
docker-entrypoint.sh
:Ceci est aujourd'hui documenté dans la documentation officielle des dockers .
PS: Vous devez installer
netcat
dans votre instance de docker si ce n'est pas disponible. Pour ce faire, ajoutez ceci à votreDocker
fichier:la source
Il existe un utilitaire prêt à l'emploi appelé " docker-wait " qui peut être utilisé pour attendre.
la source
J'ai essayé de nombreuses façons différentes, mais j'ai aimé la simplicité de ceci: https://github.com/ufoscout/docker-compose-wait
L'idée que vous pouvez utiliser ENV vars dans le fichier Compose docker soumettre une liste des services hôtes (avec les ports) qui devrait être « attendu » comme ceci:
WAIT_HOSTS: postgres:5432, mysql:3306, mongo:27017
.Supposons donc que vous ayez le fichier docker-compose.yml suivant (copier / coller à partir du fichier README ):
Ensuite, pour que les services attendent, vous devez ajouter les deux lignes suivantes à vos Dockerfiles (dans Dockerfile des services qui devraient attendre le démarrage d'autres services):
L'exemple complet d'un tel exemple Dockerfile (encore une fois à partir du référentiel de projet README ):
Pour plus de détails sur l'utilisation possible, consultez le fichier README
la source
https://github.com/ufoscout/docker-compose-wait
fonctionner la bibliothèque :) La façon dont vous utilisez cette bibliothèque ne change pas une réponse que vous pouvez utiliser une bibliothèque. La sécurité est un sujet complexe et si nous allons loin, nous devrions de toute façon vérifier ce que fait cette bibliothèque à l'intérieur, même si nous le copions :) Donc, il vaut mieux être plus précis dans votre commentaire comme: "Je déconseille fortement l'utilisation de cette bibliothèque à partir d'un lien hypertexte ". J'espère que vous êtes d'accord, merci pour un indice!en se basant sur cet article de blog https://8thlight.com/blog/dariusz-pasciak/2016/10/17/docker-compose-wait-for-dependencies.html
J'ai configuré mon
docker-compose.yml
comme indiqué ci-dessous:Ensuite, je fais pour courir =>:
docker-compose up start_dependencies
rabbitmq
le service démarrera en mode démon,start_dependencies
terminera le travail.la source
"curl", "-f", "http://localhost:15672"
pour laquelle vous devez installer lemanagement
plugin et utiliser healthcheck qui est déjà obsolète - sa meilleure réponse. Exemple de travail simple avec vérification vianc
son - downvote. ha, ok ...docker-compose run --name app-test --rm "app" bash -l -c 'echo Waiting for mysql service start... && while ! nc -z db-server 3306; do sleep 1; done && echo Connected! && /bin/bash /script/ci_tests.sh'
Dans la version 3 d'un fichier Docker Compose, vous pouvez utiliser RESTART .
Par exemple:
docker-compose.yml
Notez que j'ai utilisé depend_on au lieu de liens puisque ce dernier est déconseillé dans la version 3.
Même si cela fonctionne, ce n'est peut-être pas la solution idéale puisque vous redémarrez le conteneur Docker à chaque échec.
Jetez également un œil à RESTART_POLICY . il vous permet d'affiner la politique de redémarrage.
Lorsque vous utilisez Compose en production , il est en fait recommandé d'utiliser la stratégie de redémarrage:
la source
L'une des solutions alternatives consiste à utiliser une solution d'orchestration de conteneurs comme Kubernetes. Kubernetes prend en charge les conteneurs d'initialisation qui s'exécutent jusqu'à la fin avant que d'autres conteneurs puissent démarrer. Vous pouvez trouver un exemple ici avec le conteneur SQL Server 2017 Linux où le conteneur API utilise le conteneur init pour initialiser une base de données
https://www.handsonarchitect.com/2018/08/understand-kubernetes-object-init.html
la source
Voici l'exemple où le
main
conteneur attendworker
lorsqu'il commence à répondre aux pings:Cependant, la bonne façon est d'utiliser
healthcheck
(> = 2.1).la source
Non recommandé pour les déploiements sérieux, mais voici essentiellement une commande "wait x seconds".
Avec la
docker-compose
version,3.4
unestart_period
instruction a été ajoutéehealthcheck
. Cela signifie que nous pouvons faire ce qui suit:docker-compose.yml
:status.sh
:Ce qui se passe ici, c'est que le
healthcheck
est invoqué après 5 secondes. Cela appelle lestatus.sh
script, qui renvoie toujours "Pas de problème". Nous venons de fairezmq_client
attendre le conteneur 5 secondes avant de commencer!Remarque: il est important que vous l'ayez
version: "3.4"
. Si le.4
n'est pas là, docker-compose se plaint.la source
start_period
fait. Cette configuration signifie qu'il existe une période de grâce où les vérifications de l'état de santé échouées ne comptent pas comme des tentatives. S'il réussit tôt, il est considéré comme sain. Après la période de démarrage, un échec comptera comme une nouvelle tentative. Voir docs.docker.com/engine/reference/builder/#healthcheckJ'ai juste 2 fichiers de composition et j'en démarre un premier et un deuxième plus tard. Mon script ressemble à ça:
la source