J’utilise rabbitmq et un simple échantillon de python d’ ici avec docker-compose. Mon problème est que je dois attendre que rabbitmq soit complètement lancé. De ce que j’ai cherché jusqu’à présent, je ne sais pas comment attendre avec le conteneur x (dans mon cas) 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 aussi trouvé cette commande docker :
attendez
Utilisation: docker wait CONTAINER [CONTAINER …]
- Quelle est la différence entre les ports docker-compose et expos
- Docker Compose vs. Dockerfile – quel est le meilleur?
- Utilisation de Docker-Compose, comment exécuter plusieurs commandes
Bloquer jusqu’à ce qu’un conteneur s’arrête, puis imprimez son code de sortie.
Attendre qu’un conteneur s’arrête n’est peut-être pas ce que je cherche, mais si c’est le cas, est-il possible d’utiliser cette commande dans le fichier docker-compose.yml? Ma solution jusqu’ici est d’attendre quelques secondes et de vérifier le port, mais est-ce que c’est le moyen d’y parvenir? Si je n’attends pas, je reçois une erreur.
docker-compose.yml
worker: build: myapp/. volumes: - myapp/.:/usr/src/app:ro links: - rabbitmq rabbitmq: image: rabbitmq:3-management
python hello sample (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 worker:
FROM python:2-onbuild RUN ["pip", "install", "pika"] CMD ["python","rabbit.py"]
Mise à jour de novembre 2015 :
Un script shell ou l’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 œuvre 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 restr prêt. En plus de cela, je dois changer mon point d’entrée dans mon fichier docker.
J’espère donc avoir une réponse avec les commandes intégrées à docker-compose, ce qui, espérons-le, sera le cas si elles terminent ce problème.
Mise à jour mars 2016
Il y a une proposition pour fournir un moyen intégré pour déterminer si un conteneur est “vivant”. Docker-Compass peut donc s’en servir dans un futur proche.
Mise à jour juin 2016
Il semble que le test de santé sera intégré dans docker dans la version 1.12.0
Mise à jour de janvier 2017
J’ai trouvé une solution docker-compose, voir: Docker Compose attendre le conteneur X avant de commencer Y
Enfin trouvé une solution avec une méthode de composition de docker. 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 devez installer au moins le docker 1.12.0+. J’avais également besoin d’ étendre le fichier Dockerfile de rabbitmq , 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 lancée et publiera un message dans la queue hello. Son fonctionne maintenant (sortie).
docker-compose (version 2.1):
version: '2.1' services: app: build: app/. depends_on: rabbit: condition: service_healthy links: - rabbit rabbit: build: rabbitmq/. ports: - "15672:15672" - "5672:5672" healthcheck: test: ["CMD", "curl", "-f", "http://localhost:15672"] interval: 30s timeout: 10s resortinges: 5
sortie:
rabbit_1 | =INFO REPORT==== 25-Jan-2017::14:44:21 === rabbit_1 | closing AMQP connection <0.718.0> (172.18.0.3:36590 -> 172.18.0.2:5672) app_1 | [x] Sent 'Hello World!' healthcheckcompose_app_1 exited with code 0
Dockerfile (rabbitmq + curl):
FROM rabbitmq:3-management RUN apt-get update RUN apt-get install -y curl EXPOSE 4369 5671 5672 25672 15671 15672
La version 3 ne prend plus en charge la forme conditionnelle de dependent_on . Je me suis donc déplacé de Puis_on pour redémarrer en cas d’échec. Maintenant, mon conteneur d’application va redémarrer 2 ou 3 fois jusqu’à ce qu’il fonctionne, mais il s’agit toujours d’une fonctionnalité de création de menus fixes sans écraser le point d’entrée.
docker-compose (version 3):
version: "3" services: rabbitmq: # login guest:guest image: rabbitmq:management ports: - "4369:4369" - "5671:5671" - "5672:5672" - "25672:25672" - "15671:15671" - "15672:15672" healthcheck: test: ["CMD", "curl", "-f", "http://localhost:15672"] interval: 30s timeout: 10s resortinges: 5 app: build: ./app/ environment: - HOSTNAMERABBIT=rabbitmq restart: on-failure depends_on: - rabbitmq links: - rabbitmq
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 requirejs soient disponibles.
Dans le Dockerfile
CMD
Dockerfile
vous pouvez vous référer à votre propre script de démarrage qui vous permet de démarrer votre service de conteneur. Avant de commencer, vous attendez une dépendante comme:
Dockerfile
FROM python:2-onbuild RUN ["pip", "install", "pika"] ADD start.sh /start.sh CMD ["/start.sh"]
start.sh
#!/bin/bash while ! nc -z rabbitmq 5672; do sleep 3; done python rabbit.py
Vous devez probablement aussi installer netcat dans votre Dockerfile
. Je ne sais pas ce qui est pré-installé sur l’image de python.
Il existe quelques outils qui fournissent une logique d’attente facile à utiliser, pour des vérifications simples des ports TCP:
Pour des attentes plus complexes:
Utilisation de restart: unless-stopped
ou restart: always
peut restart: always
résoudre ce problème.
Si le container
travail s’arrête lorsque rabbitMQ n’est pas prêt, il sera redémarré jusqu’à ce qu’il le soit.
Tout récemment, ils ont ajouté la fonctionnalité depends_on
.
Modifier:
A partir de la version 2.1+, vous pouvez utiliser L’ depends_on
conjoints avec healthcheck
pour y parvenir:
De la documentation :
version: '2.1' services: web: build: . depends_on: db: condition: service_healthy redis: condition: service_started redis: image: redis db: image: redis healthcheck: test: "exit 0"
Avant la version 2.1
Vous pouvez toujours utiliser depends_on
, mais cela depends_on
que l’ ordre dans lequel les services sont lancés – pas s’ils sont prêts avant le démarrage du service dépendant.
Il semble exiger au moins la version 1.6.0.
L’utilisation ressemblerait à ceci:
version: '2' services: web: build: . depends_on: - db - redis redis: image: redis db: image: postgres
De la documentation:
Exprimer la dépendance entre les services, ce qui a deux effets:
- docker-compos up démarre les services dans l’ordre des dépendances. Dans l’exemple suivant, db et redis seront démarrés avant web.
- docker-compose up SERVICE inclura automatiquement les dépendances de SERVICE. Dans l’exemple suivant, docker-composer up web créera et démarrera db et redis.
Remarque: Si je comprends bien, cela définit l’ordre dans lequel les conteneurs sont chargés. Cela ne garantit pas que le service à l’intérieur du conteneur a réellement été chargé.
Par exemple, votre conteneur postgres peut être en hausse. Mais le service postgres lui-même peut encore être initialisé dans le conteneur.
vous pouvez aussi simplement l’append à l’option de commande, par exemple.
command: bash -c "sleep 5; start.sh"
https://github.com/docker/compose/issues/374#issuecomment-156546513
d’attendre sur un port, vous pouvez également utiliser quelque chose comme ça
command: bash -c "while ! curl -s rabbitmq:5672 > /dev/null; do echo waiting for xxx; sleep 3; done; start.sh"
pour augmenter le temps d’attente, vous pouvez pirater un peu plus:
command: bash -c "for i in {1..100} ; do if ! curl -s rabbitmq:5672 > /dev/null ; then echo waiting on rabbitmq for $i seconds; sleep $i; fi; done; start.sh"
Vous pouvez également résoudre ce problème en définissant un noeud final qui attend que le service soit actif à l’aide de netcat (à l’aide du script docker-wait ). J’aime cette approche car vous avez toujours une section de command
propre dans votre docker-compose.yml
et vous n’avez pas besoin d’append de code spécifique à docker à votre application:
version: '2' services: db: image: postgres django: build: . command: python manage.py runserver 0.0.0.0:8000 entrypoint: ./docker-entrypoint.sh db 5432 volumes: - .:/code ports: - "8000:8000" depends_on: - db
Puis votre docker-entrypoint.sh
:
#!/bin/sh postgres_host=$1 postgres_port=$2 shift 2 cmd="$@" # wait for the postgres docker to be running while ! nc $postgres_host $postgres_port; do >&2 echo "Postgres is unavailable - sleeping" sleep 1 done >&2 echo "Postgres is up - executing command" # run the command exec $cmd
Ceci est aujourd’hui documenté dans la documentation officielle de docker .
PS: vous devez installer netcat
dans votre instance de docker si ce n’est pas disponible. Pour ce faire, ajoutez ceci à votre fichier Docker
:
RUN apt-get update && apt-get install netcat-openbsd -y
Un utilitaire prêt à l’emploi appelé ” docker-wait ” peut être utilisé pour l’attente.
Pour conteneur commencer à utiliser l’utilisation
depends_on:
Pour attendre le conteneur précédent, utilisez le script d’utilisation
entrypoint: ./wait-for-it.sh db:5432
Cet article vous aidera https://docs.docker.com/compose/startup-order/
restart: on-failure
fait le tour pour moi..voir ci-dessous
--- version: '2.1' services: consumer: image: golang:alpine volumes: - ./:/go/src/srv-consumer working_dir: /go/src/srv-consumer environment: AMQP_DSN: "amqp://guest:guest@rabbitmq:5672" command: go run cmd/main.go links: - rabbitmq restart: on-failure rabbitmq: image: rabbitmq:3.7-management-alpine ports: - "15672:15672" - "5672:5672"
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:
version: "3.1" services: rabbitmq: image: rabbitmq:3.7.2-management-alpine restart: always environment: RABBITMQ_HIPE_COMPILE: 1 RABBITMQ_MANAGEMENT: 1 RABBITMQ_VM_MEMORY_HIGH_WATERMARK: 0.2 RABBITMQ_DEFAULT_USER: "rabbitmq" RABBITMQ_DEFAULT_PASS: "rabbitmq" ports: - "15672:15672" - "5672:5672" volumes: - data:/var/lib/rabbitmq:rw start_dependencies: image: alpine:latest links: - rabbitmq command: > /bin/sh -c " echo Waiting for rabbitmq service start...; while ! nc -z rabbitmq 5672; do sleep 1; done; echo Connected!; " volumes: data: {}
Ensuite, je fais pour run =>:
docker-compose up start_dependencies
rabbitmq
service rabbitmq
démarrera en mode démon, start_dependencies
achèvera le travail.