Estoy usando rabbitmq y una simple muestra de python de aquí junto con docker-compose. Mi problema es que necesito esperar a que rabbitmq se inicie por completo. Por lo que busqué hasta ahora, no sé cómo esperar con el contenedor x (en mi caso trabajador) hasta que se inicie y (rabbitmq).
Encontré esta publicación de blog donde comprueba si el otro host está en línea. También encontré este comando docker :
Espere
Uso: docker wait CONTENEDOR [CONTENEDOR ...]
Bloquee hasta que un contenedor se detenga, luego imprima su código de salida.
Esperar a que se detenga un contenedor quizás no sea lo que estoy buscando, pero si lo es, ¿es posible usar ese comando dentro de docker-compose.yml? Mi solución hasta ahora es esperar unos segundos y verificar el puerto, pero ¿es esta la forma de lograr esto? Si no espero me sale un error.
docker-compose.yml
worker:
build: myapp/.
volumes:
- myapp/.:/usr/src/app:ro
links:
- rabbitmq
rabbitmq:
image: rabbitmq:3-management
Python hola muestra (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 para trabajador:
FROM python:2-onbuild
RUN ["pip", "install", "pika"]
CMD ["python","rabbit.py"]
Actualización de noviembre de 2015 :
Un script de shell o esperar dentro de su programa es quizás una posible solución. Pero después de ver este problema , estoy buscando un comando o función de docker / docker-compose.
Mencionan una solución para implementar un control de salud, que puede ser la mejor opción. Una conexión tcp abierta no significa que su servicio esté listo o pueda permanecer listo. Además de eso, necesito cambiar mi punto de entrada en mi dockerfile.
Así que espero una respuesta con los comandos a bordo de Docker-compose, que con suerte será el caso si terminan este problema.
Actualización de marzo de 2016
Existe una propuesta para proporcionar una forma integrada de determinar si un contenedor está "vivo". Por lo tanto, Docker-compose puede usarlo en un futuro próximo.
Actualización de junio de 2016
Parece que el chequeo de salud se integrará en Docker en la versión 1.12.0
Actualización enero 2017
Encontré una solución docker-compose ver: Docker Compose espera el contenedor X antes de comenzar Y
fuente
Respuestas:
Finalmente encontré una solución con un método docker-compose. Desde el formato de archivo docker-compose 2.1 puede definir comprobaciones de estado .
Lo hice en un proyecto de ejemplo que necesita instalar al menos Docker 1.12.0+. También necesitaba ampliar el Dockerfile rabbitmq-management , porque curl no está instalado en la imagen oficial.
Ahora pruebo si la página de administración del rabbitmq-container está disponible. Si el rizo termina con el código de salida 0, la aplicación de contenedor (python pika) se iniciará y publicará un mensaje en la cola de saludo. Ahora está funcionando (salida).
docker-compose (versión 2.1):
salida:
Dockerfile (rabbitmq + curl):
La versión 3 ya no admite la forma de condición de dependen_on . Así que me mudé de dependen_on para reiniciar en caso de falla. Ahora mi contenedor de aplicaciones se reiniciará 2-3 veces hasta que funcione, pero sigue siendo una función de compilación acoplable sin sobrescribir el punto de entrada.
docker-compose (versión 3):
fuente
ping
usa ICMP, por lo que no admite puertos TCP. Tal veznc
para probar un puerto TCP. Probablemente mejor usarpsql -h localhost -p 5432
y consultar algo.condition
forma dedepends_on
, perodepends_on
todavía está alrededor en v3depends_on
lacondition
ha quitado?Nativamente eso no es posible, todavía. Consulte también esta solicitud de función .
Hasta ahora, debe hacer eso en sus contenedores
CMD
para esperar hasta que todos los servicios requeridos estén allí.En los
Dockerfile
mensajes deCMD
correo electrónico, puede consultar su propio script de inicio que envuelve el inicio de su servicio de contenedor. Antes de comenzar, espera a uno dependiente como:Dockerfile
start.sh
Probablemente también necesites instalar netcat en tu
Dockerfile
. No sé qué está preinstalado en la imagen de Python.Existen algunas herramientas que proporcionan una lógica de espera fácil de usar, para verificaciones simples de puertos tcp:
Para esperas más complejas:
fuente
Usando
restart: unless-stopped
orestart: always
puede resolver este problema.Si el trabajador se
container
detiene cuando rabbitMQ no está listo, se reiniciará hasta que lo esté.fuente
Recientemente han agregado la
depends_on
función .Editar:
A partir de compose la versión 2.1+, puede usarlo
depends_on
en conjunto conhealthcheck
para lograr esto:De los documentos :
Antes de la versión 2.1
Todavía puede usar
depends_on
, pero solo afecta el orden en que se inician los servicios, no si están listos antes de que se inicie el servicio dependiente.Parece requerir al menos la versión 1.6.0.
El uso se vería así:
De los documentos:
Nota: Según tengo entendido, aunque esto establece el orden en que se cargan los contenedores. No garantiza que el servicio dentro del contenedor se haya cargado realmente.
Por ejemplo, el contenedor de postgres podría estar activo. Pero el servicio postgres en sí mismo aún podría estar inicializándose dentro del contenedor.
fuente
depends_on
". docs.docker.com/compose/compose-file/#dependsondepends_on
no espera hasta que el contenedor esté enready
estado (lo que sea que eso signifique en su caso). Solo espera hasta que el contenedor esté en estado 'en ejecución'.También puede agregarlo a la opción de comando, por ejemplo.
https://github.com/docker/compose/issues/374#issuecomment-156546513
esperar en un puerto también puedes usar algo como esto
para aumentar el tiempo de espera puedes hackear un poco más:
fuente
restart: on-failure
hizo el truco para mí ... ver abajofuente
Para el contenedor comenzar a ordenar el uso
Para esperar el inicio del contenedor anterior, use el script
Este artículo lo ayudará a https://docs.docker.com/compose/startup-order/
fuente
También puede resolver esto estableciendo un punto final que espere a que el servicio esté activo utilizando netcat (utilizando el script docker-wait ). Me gusta este enfoque, ya que todavía tiene una
command
sección limpia en sudocker-compose.yml
y no necesita agregar código específico de Docker a su aplicación:Entonces tu
docker-entrypoint.sh
:Esto se documenta en la actualidad el funcionario documentación ventana acoplable .
PD: debe instalarlo
netcat
en su instancia de docker si no está disponible. Para hacerlo, agregue esto a suDocker
archivo:fuente
Hay una utilidad lista para usar llamada " docker-wait " que se puede usar para esperar.
fuente
Intenté muchas maneras diferentes, pero me gustó la simplicidad de esto: https://github.com/ufoscout/docker-compose-wait
La idea de que se puede utilizar ENV vars en el archivo de cargador de muelle de redacción para presentar una lista de hosts de servicios (con puertos) que debe ser "esperado" de esta manera:
WAIT_HOSTS: postgres:5432, mysql:3306, mongo:27017
.Entonces, supongamos que tiene el siguiente archivo docker-compose.yml (copy / past de repo README ):
A continuación, para que los servicios esperen, debe agregar las siguientes dos líneas a sus Dockerfiles (en Dockerfile de los servicios que deben esperar a que otros servicios comiencen):
El ejemplo completo de tal Dockerfile de muestra (nuevamente desde el proyecto REpo README ):
Para otros detalles sobre el posible uso, consulte README
fuente
https://github.com/ufoscout/docker-compose-wait
biblioteca funcione :) La forma en que usas esa biblioteca no cambia una respuesta de que puedes utilizar algo de lib. La seguridad es un tema complejo y, si llegamos lejos, deberíamos comprobar qué hace esa biblioteca en el interior de todos modos, incluso si la COPIAMOS :) Por lo tanto, es mejor ser más específico en su comentario como: "Recomiendo encarecidamente el uso de esa biblioteca desde hipervínculo ". Espero que estés de acuerdo, gracias por una pista!basándose en esta publicación de blog https://8thlight.com/blog/dariusz-pasciak/2016/10/17/docker-compose-wait-for-dependencies.html
Configuré mi
docker-compose.yml
como se muestra a continuación:Entonces lo hago para ejecutar =>:
docker-compose up start_dependencies
rabbitmq
El servicio comenzará en modo demonio,start_dependencies
finalizará el trabajo.fuente
"curl", "-f", "http://localhost:15672"
de la cual necesitas instalar elmanagement
complemento y usar un chequeo de salud que ya no se utiliza - es la mejor respuesta. Ejemplo de trabajo simple con cheque a través denc
su - downvote. ja, 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'
En la versión 3 de un archivo Docker Compose, puede usar RESTART .
Por ejemplo:
docker-compose.yml
Tenga en cuenta que utilicé depende_en lugar de enlaces, ya que este último está en desuso en la versión 3.
Aunque funciona, puede que no sea la solución ideal, ya que reinicia el contenedor acoplable en cada falla.
Eche un vistazo a RESTART_POLICY también. le permite ajustar la política de reinicio.
Cuando usa Compose en producción , en realidad es una buena práctica usar la política de reinicio:
fuente
Una de las soluciones alternativas es utilizar una solución de organización de contenedores como Kubernetes. Kubernetes tiene soporte para contenedores init que se ejecutan hasta su finalización antes de que otros contenedores puedan comenzar. Puede encontrar un ejemplo aquí con el contenedor Linux de SQL Server 2017 donde el contenedor API usa el contenedor init para inicializar una base de datos
https://www.handsonarchitect.com/2018/08/understand-kubernetes-object-init.html
fuente
Aquí está el ejemplo donde el
main
contenedor esperaworker
cuando comienza a responder pings:Sin embargo, la forma correcta es usar
healthcheck
(> = 2.1).fuente
No se recomienda para implementaciones serias, pero aquí es esencialmente un comando "esperar x segundos".
Con la
docker-compose
versión se ha agregado3.4
unastart_period
instrucciónhealthcheck
. Esto significa que podemos hacer lo siguiente:docker-compose.yml
:status.sh
:Lo que sucede aquí es que
healthcheck
se invoca después de 5 segundos. Esto llama alstatus.sh
script, que siempre devuelve "No hay problema". ¡Acabamos de hacer que elzmq_client
contenedor espere 5 segundos antes de comenzar!Nota: es importante que tengas
version: "3.4"
. Si.4
no está allí, Docker-compose se queja.fuente
start_period
hace. Esa configuración significa que hay un período de gracia en el que las comprobaciones de estado fallidas no cuentan como reintentos. Si tiene éxito temprano, se considera saludable. Después del período de inicio, una falla contará como un reintento. Ver docs.docker.com/engine/reference/builder/#healthcheckSolo tengo 2 archivos de composición y comienzo uno primero y el segundo más tarde. Mi guión se ve así:
fuente