Estou usando rabbitmq e um exemplo simples de python daqui em conjunto com o docker-compose. Meu problema é que preciso aguardar a inicialização completa do rabbitmq. Pelo que pesquisei até agora, não sei como esperar com o contêiner x (no meu assistente de caso) até que y (rabbitmq) seja iniciado.
Encontrei este blog onde ele verifica se o outro host está online. Eu também encontrei este comando docker :
esperar
Uso: docker wait CONTAINER [CONTAINER ...]
Bloqueie até que um contêiner pare e imprima seu código de saída.
Esperar a parada de um contêiner talvez não seja o que estou procurando, mas, se for, é possível usar esse comando dentro do docker-compose.yml? Até agora, minha solução é aguardar alguns segundos e verificar a porta, mas é esse o caminho para conseguir isso? Se eu não esperar, recebo um erro.
docker-compose.yml
worker:
build: myapp/.
volumes:
- myapp/.:/usr/src/app:ro
links:
- rabbitmq
rabbitmq:
image: rabbitmq:3-management
Olá, exemplo python (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 trabalhador:
FROM python:2-onbuild
RUN ["pip", "install", "pika"]
CMD ["python","rabbit.py"]
Atualização de novembro de 2015 :
Um script de shell ou aguardar dentro do seu programa é talvez uma solução possível. Mas, depois de ver esse problema , estou procurando um comando ou recurso do docker / docker-componen.
Eles mencionam uma solução para implementar uma verificação de saúde, que pode ser a melhor opção. Uma conexão tcp aberta não significa que seu serviço está pronto ou pode permanecer pronto. Além disso, preciso alterar meu ponto de entrada no meu arquivo docker.
Portanto, espero obter uma resposta com os comandos docker-compose on board, que, esperançosamente, serão o caso se eles terminarem esse problema.
Atualização de março de 2016
Existe uma proposta para fornecer uma maneira interna de determinar se um contêiner está "vivo". Portanto, o docker-compose pode utilizá-lo no futuro próximo.
Atualização junho de 2016
Parece que a verificação de saúde será integrada ao docker na versão 1.12.0
Atualização de janeiro de 2017
Encontrei uma solução docker-compose, consulte: Docker Compose, aguarde o contêiner X antes de iniciar Y
fonte
Respostas:
Finalmente encontrei uma solução com um método docker-compose. Desde o formato de arquivo 2.1 do docker-compose, você pode definir verificações de saúde .
Fiz isso em um projeto de exemplo que você precisa instalar pelo menos o docker 1.12.0+. Eu também precisava estender o Dockerfile rabbitmq-management , porque o curl não está instalado na imagem oficial.
Agora, testo se a página de gerenciamento do rabbitmq-container está disponível. Se a curvatura terminar com o exitcode 0, o aplicativo de contêiner (python pika) será iniciado e publicará uma mensagem na fila hello. Agora está funcionando (saída).
docker-compose (versão 2.1):
resultado:
Arquivo de encaixe (rabbitmq + curl):
A versão 3 não suporta mais o formato de condição de depende_on . Então, mudei de depende_on para reiniciar em caso de falha. Agora, meu contêiner de aplicativos será reiniciado 2-3 vezes até que esteja funcionando, mas ainda é um recurso de composição do docker sem substituir o ponto de entrada.
docker-compose (versão 3):
fonte
ping
usa ICMP, portanto, não suporta portas TCP. Talveznc
para testar uma porta TCP. Provavelmente é melhor usarpsql -h localhost -p 5432
e consultar algo.condition
forma dedepends_on
foi removida, masdepends_on
ela ainda existe na v3 #depends_on
comcondition
foi removido?Nativamente, isso ainda não é possível. Veja também esta solicitação de recurso .
Até agora, você precisa fazer isso em seus contêineres
CMD
para aguardar até que todos os serviços necessários estejam lá.Nos
Dockerfile
s,CMD
você pode se referir ao seu próprio script de início que encerra a inicialização do serviço de contêiner. Antes de iniciá-lo, aguarde um dependendo, como:Dockerfile
start.sh
Provavelmente você também precisa instalar o netcat no seu
Dockerfile
. Não sei o que é pré-instalado na imagem python.Existem algumas ferramentas disponíveis que fornecem lógica de espera fácil de usar, para verificações simples da porta tcp:
Para esperas mais complexas:
fonte
Usando
restart: unless-stopped
ourestart: always
pode resolver esse problema.Se o worker
container
parar quando o rabbitMQ não estiver pronto, ele será reiniciado até que esteja.fonte
Recentemente, eles adicionaram o
depends_on
recurso .Editar:
A partir do compor versão 2.1+, você pode usar
depends_on
em conjunto comhealthcheck
para conseguir isso:Dos documentos :
Antes da versão 2.1
Você ainda pode usar
depends_on
, mas isso afeta apenas a ordem em que os serviços são iniciados - e não se eles estiverem prontos antes do serviço dependente ser iniciado.Parece exigir pelo menos a versão 1.6.0.
O uso ficaria assim:
Dos documentos:
Nota: Pelo que entendi, embora isso defina a ordem em que os contêineres são carregados. Não garante que o serviço dentro do contêiner tenha realmente sido carregado.
Por exemplo, o contêiner do postgres pode estar ativo. Mas o próprio serviço postgres ainda pode estar inicializando no contêiner.
fonte
depends_on
." docs.docker.com/compose/compose-file/#dependsondepends_on
não espera até que o contêiner esteja noready
estado (o que isso pode significar no seu caso). Ele aguarda apenas até que o contêiner esteja no estado 'running'.você também pode adicioná-lo à opção de comando, por exemplo.
https://github.com/docker/compose/issues/374#issuecomment-156546513
para esperar em uma porta, você também pode usar algo como isto
Para aumentar o tempo de espera, você pode hackear um pouco mais:
fonte
restart: on-failure
fez o truque para mim .. veja abaixofonte
Para pedidos de início de contêiner, use
Para aguardar o contêiner anterior, comece a usar o script
Este artigo ajudará você a https://docs.docker.com/compose/startup-order/
fonte
Você também pode resolver isso definindo um terminal que aguarda a ativação do serviço usando o netcat (usando o script docker-wait ). Eu gosto dessa abordagem, pois você ainda possui uma
command
seção limpa no seudocker-compose.yml
e não precisa adicionar código específico do docker ao seu aplicativo:Então o seu
docker-entrypoint.sh
:Atualmente, isso está documentado na documentação oficial da janela de encaixe .
PS: você deve instalar
netcat
na sua instância do docker se isso não estiver disponível. Para fazer isso, adicione isso ao seuDocker
arquivo:fonte
Existe um utilitário pronto para uso chamado " docker-wait " que pode ser usado para aguardar.
fonte
Tentei de várias maneiras diferentes, mas gostei da simplicidade disso: https://github.com/ufoscout/docker-compose-wait
A idéia de que você pode usar ENV vars no arquivo janela de encaixe compor para apresentar uma lista de hosts de serviços (com portas), que deve ser "esperado" como este:
WAIT_HOSTS: postgres:5432, mysql:3306, mongo:27017
.Então, digamos que você tenha o seguinte arquivo docker-compose.yml (copie / cole do repo README ):
Em seguida, para que os serviços esperem, você deve adicionar as duas linhas a seguir aos seus Dockerfiles (no Dockerfile dos serviços que devem aguardar o início de outros serviços):
O exemplo completo desse exemplo Dockerfile (novamente no repositório README do projeto ):
Para outros detalhes sobre o possível uso, consulte o arquivo LEIA-ME
fonte
https://github.com/ufoscout/docker-compose-wait
biblioteca funcionar :) A maneira como você usa essa biblioteca não altera a resposta de que você pode utilizar alguma lib. A segurança é um tópico complexo e, se formos longe, devemos verificar o que essa biblioteca está fazendo lá dentro, mesmo que a copiem :) É melhor ser mais específico em seu comentário, como: "Eu recomendo fortemente o uso dessa biblioteca do hiperlink ". Espero que você concorde, obrigado por uma dica!com base nesta postagem do blog https://8thlight.com/blog/dariusz-pasciak/2016/10/17/docker-compose-wait-for-dependencies.html
Eu configurei o meu
docker-compose.yml
como mostrado abaixo:Então eu faço para executar =>:
docker-compose up start_dependencies
rabbitmq
O serviço iniciará no modo daemon,start_dependencies
finalizará o trabalho.fonte
"curl", "-f", "http://localhost:15672"
para o qual você precisa instalar omanagement
plugin e usando o healthcheck que já foi descontinuado - sua melhor resposta. Exemplo simples de trabalho com cheque através donc
seu - voto negativo. 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'
Na versão 3 de um arquivo Docker Compose, você pode usar RESTART .
Por exemplo:
docker-compose.yml
Observe que eu usei o Depend_on em vez de links, pois o último está obsoleto na versão 3.
Mesmo que funcione, pode não ser a solução ideal, pois você reinicia o contêiner do docker a cada falha.
Ter um olhar para RESTART_POLICY também. permite ajustar a política de reinicialização.
Ao usar o Redigir na produção , é realmente recomendável usar a política de reinicialização:
fonte
Uma das soluções alternativas é usar uma solução de orquestração de contêiner como o Kubernetes. O Kubernetes tem suporte para contêineres init que são concluídos antes que outros contêineres possam iniciar. Você pode encontrar um exemplo aqui com o contêiner do SQL Server 2017 Linux em que o contêiner da API usa o contêiner init para inicializar um banco de dados
https://www.handsonarchitect.com/2018/08/understand-kubernetes-object-init.html
fonte
Aqui está o exemplo em que o
main
contêiner aguardaworker
quando começa a responder por pings:No entanto, a maneira correta é usar
healthcheck
(> = 2.1).fonte
Não recomendado para implantações sérias, mas aqui está essencialmente um comando "wait x seconds".
Com a
docker-compose
versão,3.4
umastart_period
instrução foi adicionada ahealthcheck
. Isso significa que podemos fazer o seguinte:docker-compose.yml
:status.sh
:O que acontece aqui é que o
healthcheck
é invocado após 5 segundos. Isso chama ostatus.sh
script, que sempre retorna "Sem problemas". Acabamos de fazer ozmq_client
recipiente esperar 5 segundos antes de começar!Nota: É importante que você tenha
version: "3.4"
. Se.4
não houver, o docker-compose reclama.fonte
start_period
faz. Essa configuração significa que há um período de cortesia em que as verificações de integridade com falha não contam como novas tentativas. Se for bem-sucedido cedo, é considerado saudável. Após o período de início, uma falha será contada como uma nova tentativa. Veja docs.docker.com/engine/reference/builder/#healthcheckEu só tenho 2 arquivos de composição e inicio um primeiro e o segundo mais tarde. Meu script é assim:
fonte