Ich verwende Rabbitmq und eine einfache Python-Probe von hier zusammen mit Docker-Compose. Mein Problem ist, dass ich warten muss, bis rabbitmq vollständig gestartet ist. Nach dem, was ich bisher gesucht habe, weiß ich nicht, wie ich mit Container x (in meinem Fallbearbeiter) warten soll, bis y (rabbitmq) gestartet wird.
Ich habe diesen Blogpost gefunden, in dem er überprüft, ob der andere Host online ist. Ich habe auch diesen Docker-Befehl gefunden :
warten
Verwendung: Docker warten CONTAINER [CONTAINER ...]
Blockieren Sie, bis ein Container stoppt, und drucken Sie dann seinen Exit-Code.
Das Warten auf das Stoppen eines Containers ist vielleicht nicht das, wonach ich suche, aber wenn ja, ist es möglich, diesen Befehl in der Datei docker-compose.yml zu verwenden? Meine bisherige Lösung besteht darin, einige Sekunden zu warten und den Port zu überprüfen. Ist dies jedoch der Weg, um dies zu erreichen? Wenn ich nicht warte, erhalte ich eine Fehlermeldung.
docker-compose.yml
worker:
build: myapp/.
volumes:
- myapp/.:/usr/src/app:ro
links:
- rabbitmq
rabbitmq:
image: rabbitmq:3-management
Python Hallo Probe (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 für Arbeiter:
FROM python:2-onbuild
RUN ["pip", "install", "pika"]
CMD ["python","rabbit.py"]
Update November 2015 :
Ein Shell-Skript oder das Warten in Ihrem Programm ist möglicherweise eine mögliche Lösung. Aber nachdem ich dieses Problem gesehen habe, suche ich nach einem Befehl oder einer Funktion von Docker / Docker-Compose selbst.
Sie erwähnen eine Lösung für die Durchführung eines Gesundheitschecks, die möglicherweise die beste Option ist. Eine offene TCP-Verbindung bedeutet nicht, dass Ihr Dienst bereit ist oder möglicherweise bereit bleibt. Außerdem muss ich meinen Einstiegspunkt in meiner Docker-Datei ändern.
Ich hoffe also auf eine Antwort mit Docker-Compose-On-Board-Befehlen, die hoffentlich der Fall sein wird, wenn sie dieses Problem lösen.
Update März 2016
Es gibt einen Vorschlag für die Bereitstellung einer integrierten Methode, um festzustellen, ob ein Container "lebt". Docker-Compose kann es also möglicherweise in naher Zukunft nutzen.
Update Juni 2016
Es scheint , dass der Gesundheitscheck wird integriert in Version 1.12.0 in Docker
Update Januar 2017
Ich habe eine Docker-Compose-Lösung gefunden, siehe: Docker Compose Warten Sie auf Container X, bevor Sie Y starten
quelle
Antworten:
Endlich eine Lösung mit einer Docker-Compose-Methode gefunden. Seit Docker-Compose-Dateiformat 2.1 können Sie Healthchecks definieren .
Ich habe es in einem Beispielprojekt gemacht, für das Sie mindestens Docker 1.12.0+ installieren müssen. Ich musste auch die Docker-Datei für das Rabbitmq-Management erweitern , da Curl nicht auf dem offiziellen Image installiert ist.
Jetzt teste ich, ob die Management-Seite des rabbitmq-Containers verfügbar ist. Wenn Curl mit Exitcode 0 endet, wird die Container-App (Python Pika) gestartet und eine Nachricht in der Hallo-Warteschlange veröffentlicht. Es funktioniert jetzt (Ausgabe).
Docker-Compose (Version 2.1):
Ausgabe:
Dockerfile (rabbitmq + curl):
Version 3 unterstützt die Bedingungsform abhängige_on nicht mehr . Also bin ich von abhängigen_on umgezogen, um bei einem Fehler neu zu starten. Jetzt wird mein App-Container 2-3 Mal neu gestartet, bis er funktioniert, aber es handelt sich immer noch um eine Docker-Compose-Funktion, ohne den Einstiegspunkt zu überschreiben.
Docker-Compose (Version 3):
quelle
ping
verwendet ICMP und unterstützt daher keine TCP-Ports. Vielleichtnc
um einen TCP-Port zu testen. Wahrscheinlich besser,psql -h localhost -p 5432
etwas zu verwenden und abzufragen.condition
Form vondepends_on
entfernt wurde, aber esdepends_on
gibt sie immer noch in v3depends_on
withcondition
entfernt wurde?Nativ ist das noch nicht möglich. Siehe auch diese Funktionsanforderung .
Bisher müssen Sie dies in Ihren Containern tun, um
CMD
zu warten, bis alle erforderlichen Dienste vorhanden sind.In
Dockerfile
s könnenCMD
Sie auf Ihr eigenes Startskript verweisen, das den Start Ihres Containerservices abschließt. Bevor Sie es starten, warten Sie auf eine abhängige wie:Dockerfile
start.sh
Wahrscheinlich müssen Sie netcat auch in Ihrem installieren
Dockerfile
. Ich weiß nicht, was auf dem Python-Image vorinstalliert ist.Es gibt einige Tools, die eine benutzerfreundliche Wartelogik für einfache TCP-Port-Überprüfungen bieten:
Für komplexere Wartezeiten:
quelle
Verwenden
restart: unless-stopped
oderrestart: always
kann dieses Problem lösen.Wenn der Worker
container
stoppt, wenn rabbitMQ nicht bereit ist, wird er neu gestartet, bis er fertig ist.quelle
Vor kurzem haben sie die
depends_on
Funktion hinzugefügt .Bearbeiten:
Ab Compose Version 2.1+ können Sie dies
depends_on
in Verbindung mit verwendenhealthcheck
, um dies zu erreichen:Aus den Dokumenten :
Vor Version 2.1
Sie können weiterhin verwenden
depends_on
, dies wirkt sich jedoch nur auf die Reihenfolge aus, in der die Dienste gestartet werden - nicht, wenn sie vor dem Start des abhängigen Dienstes bereit sind.Es scheint mindestens Version 1.6.0 zu erfordern.
Die Verwendung würde ungefähr so aussehen:
Aus den Dokumenten:
Hinweis: Soweit ich weiß, wird hierdurch die Reihenfolge festgelegt, in der Container geladen werden. Es kann nicht garantiert werden, dass der Dienst im Container tatsächlich geladen wurde.
Beispielsweise ist Ihr Postgres- Container möglicherweise aktiv. Möglicherweise wird der Postgres-Dienst selbst noch im Container initialisiert.
quelle
depends_on
." docs.docker.com/compose/compose-file/#dependsondepends_on
wartet nicht, bis sich der Container imready
Status befindet (was auch immer das in Ihrem Fall bedeuten kann). Es wird nur gewartet, bis sich der Container im Status "Ausführen" befindet.Sie können es auch einfach zur Befehlsoption hinzufügen, z.
https://github.com/docker/compose/issues/374#issuecomment-156546513
Um auf einen Port zu warten, können Sie auch so etwas verwenden
Um die Wartezeit zu verlängern, können Sie ein bisschen mehr hacken:
quelle
restart: on-failure
habe den Trick für mich gemacht ... siehe untenquelle
Für Containerbestellung verwenden
Verwenden Sie zum Warten auf den vorherigen Container-Start das Skript
Dieser Artikel hilft Ihnen https://docs.docker.com/compose/startup-order/
quelle
Sie können dieses Problem auch lösen, indem Sie mithilfe von netcat (mithilfe des Docker-Wait- Skripts) einen Endpunkt festlegen, der darauf wartet, dass der Dienst aktiv ist . Ich mag diesen Ansatz, da Sie immer noch einen sauberen
command
Abschnitt in Ihrem habendocker-compose.yml
und Ihrer Anwendung keinen Docker-spezifischen Code hinzufügen müssen:Dann ist dein
docker-entrypoint.sh
:Dies ist heutzutage in der offiziellen Docker-Dokumentation dokumentiert .
PS: Sie sollten
netcat
in Ihrer Docker-Instanz installieren, wenn dies nicht verfügbar ist. Fügen Sie dazu Folgendes zu IhrerDocker
Datei hinzu:quelle
Es gibt ein gebrauchsfertiges Dienstprogramm namens " Docker-Wait ", das zum Warten verwendet werden kann.
quelle
Versuchte viele verschiedene Möglichkeiten, mochte aber die Einfachheit: https://github.com/ufoscout/docker-compose-wait
Die Idee, dass Sie ENV-Variablen in der Docker-Erstellungsdatei verwenden können, um eine Liste von Diensthosts (mit Ports) zu senden, auf die wie folgt "gewartet" werden sollte :
WAIT_HOSTS: postgres:5432, mysql:3306, mongo:27017
.Nehmen wir also an, Sie haben die folgende Datei docker-compose.yml (Kopie / Vergangenheit von Repo README ):
Damit die Dienste warten können, müssen Sie Ihren Docker-Dateien die folgenden zwei Zeilen hinzufügen (in die Docker-Datei der Dienste, die auf den Start anderer Dienste warten sollen):
Das vollständige Beispiel einer solchen Beispiel-Docker-Datei (wieder aus dem Projekt-Repo README ):
Weitere Einzelheiten zur möglichen Verwendung finden Sie unter README
quelle
https://github.com/ufoscout/docker-compose-wait
Bibliothek funktioniert :) Die Art und Weise, wie Sie diese Bibliothek verwenden, ändert nichts an der Antwort, dass Sie eine Bibliothek verwenden können. Sicherheit ist ein komplexes Thema, und wenn wir weit gehen, sollten wir überprüfen, was diese Bibliothek ohnehin tut, auch wenn wir sie KOPIEREN :) Um es genauer zu sagen: "Ich empfehle dringend, diese Bibliothek nicht zu verwenden." vom Hyperlink ". Hoffe du stimmst zu, danke für einen Hinweis!basierend auf diesem Blog-Beitrag https://8thlight.com/blog/dariusz-pasciak/2016/10/17/docker-compose-wait-for-dependencies.html
Ich habe meine
docker-compose.yml
wie unten gezeigt konfiguriert :Dann mache ich für run =>:
docker-compose up start_dependencies
rabbitmq
Der Dienst wird im Daemon-Modus gestartet undstart_dependencies
die Arbeit beendet.quelle
"curl", "-f", "http://localhost:15672"
dasmanagement
Plugin installieren müssen, und verwenden Sie den bereits veralteten Healthcheck - die beste Antwort. Einfaches Arbeitsbeispiel mit Check vianc
its - 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'
In Version 3 einer Docker Compose-Datei können Sie RESTART verwenden .
Zum Beispiel:
docker-compose.yml
Beachten Sie, dass ich abhängige_on anstelle von Links verwendet habe, da letztere in Version 3 veraltet sind.
Obwohl es funktioniert, ist es möglicherweise nicht die ideale Lösung, da Sie den Docker-Container bei jedem Fehler neu starten.
Schauen Sie sich auch RESTART_POLICY an. Damit können Sie die Neustartrichtlinie optimieren.
Wenn Sie Compose in der Produktion verwenden, empfiehlt es sich, die Neustartrichtlinie zu verwenden:
quelle
Eine der alternativen Lösungen ist die Verwendung einer Container-Orchestrierungslösung wie Kubernetes. Kubernetes unterstützt Init-Container, die vollständig ausgeführt werden, bevor andere Container gestartet werden können. Hier finden Sie ein Beispiel für den Linux-Container SQL Server 2017, in dem der API-Container den Init-Container zum Initialisieren einer Datenbank verwendet
https://www.handsonarchitect.com/2018/08/understand-kubernetes-object-init.html
quelle
Hier ist das Beispiel, in dem der
main
Container wartet,worker
wenn er auf Pings reagiert:Der richtige Weg ist jedoch die Verwendung von
healthcheck
(> = 2.1).quelle
Nicht für ernsthafte Bereitstellungen empfohlen, aber hier ist im Wesentlichen ein Befehl "Warten x Sekunden".
Mit der
docker-compose
Version wurde3.4
einestart_period
Anweisung hinzugefügthealthcheck
. Dies bedeutet, dass wir Folgendes tun können:docker-compose.yml
::status.sh
::Was hier passiert ist, dass das
healthcheck
nach 5 Sekunden aufgerufen wird. Dies ruft dasstatus.sh
Skript auf, das immer "Kein Problem" zurückgibt. Wir haben gerade denzmq_client
Container 5 Sekunden warten lassen, bevor wir anfangen!Hinweis: Es ist wichtig, dass Sie haben
version: "3.4"
. Wenn das.4
nicht da ist, beschwert sich Docker-Compose.quelle
start_period
. Diese Konfiguration bedeutet, dass es eine Nachfrist gibt, in der fehlgeschlagene Integritätsprüfungen nicht als Wiederholungsversuche gelten. Wenn es früh gelingt, gilt es als gesund. Nach der Startperiode zählt ein Fehler als erneuter Versuch. Siehe docs.docker.com/engine/reference/builder/#healthcheckIch habe nur 2 Compose-Dateien und beginne eine erste und eine zweite später. Mein Skript sieht so aus:
quelle