Docker Compose在开始Y之前等待容器X.

我从这里使用rabbitmq和一个简单的python样本,以及docker-compose。 我的问题是,我需要等待rabbitmq完全启动。 从我到目前为止search,我不知道如何等待容器x(在我的情况下,工人),直到y(rabbitmq)开始。

我发现这个博客post ,他检查其他主机是否在线。 我也发现这个docker命令 :

等待

用法:docker等待CONTAINER [CONTAINER …]

阻塞,直到一个容器停止,然后打印出口代码。

等待容器停止也许不是我正在寻找,但如果是,是否有可能在docker-compose.yml中使用该命令? 我的解决scheme到目前为止是等待几秒钟,并检查端口,但这是实现这一目标的方式? 如果我不等,我得到一个错误。

泊坞窗,compose.yml

worker: build: myapp/. volumes: - myapp/.:/usr/src/app:ro links: - rabbitmq rabbitmq: image: rabbitmq:3-management 

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:

 FROM python:2-onbuild RUN ["pip", "install", "pika"] CMD ["python","rabbit.py"] 

2015年11月更新

一个shell脚本或等待你的程序可能是一个可能的解决scheme。 但是在看到这个问题后,我正在寻找一个docker / docker的命令或特性 – 自己编写。

他们提到实施健康检查的解决scheme,这可能是最好的select。 开放的TCP连接并不意味着你的服务已经准备好,或者可以保持准备好。 除此之外,我需要更改我的dockerfile中的入口点。

所以我希望能用docker-compose的命令来回答这个问题,如果他们完成这个问题,希望是这样。

2016年3月更新

有一个build议提供一个内置的方式来确定一个容器是否“活着”。 所以docker员可以在不久的将来使用它。

2016年6月更新

看来健康检查将被集成到版本1.12.0中的docker中

2017年1月更新

我发现一个docker-compose解决scheme请参阅: Docker Compose在启动Y之前等待容器X.

最后find了一个docker-compose方法的解决scheme。 由于docker组成文件格式2.1,您可以定义健康检查 。

我做了一个示例项目,您至less需要安装Docker 1.12.0+。 我还需要扩展rabbitmq-management Dockerfile ,因为官方图片上没有安装curl。

现在我testing一下rabbitmq-container的pipe理页面是否可用。 如果curl以exitcode 0结束,容器应用程序(python pika)将被启动并将消息发布到hello队列。 它现在工作(输出)。

泊坞窗-撰写:

 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 retries: 5 

输出:

 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 

本地,这是不可能的,但。 另请参阅此function请求 。

到目前为止,您需要在您的容器CMD执行此操作,以等待所有必需的服务在那里。

DockerfileCMD你可以引用你自己的启动脚本来启动你的容器服务。 在你开始之前,你需要等待一个依赖的:

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 

也许你需要在你的Dockerfile安装netcat。 我不知道什么是预先安装在Python图像。

有几个工具提供简单的等待逻辑,简单的TCP端口检查:

  • 等待换它
  • dockerize

对于更复杂的等待:

  • 高斯 – 解释博客

使用restart: unless-stoppedrestart: always可以解决这个问题。

当rabbitMQ没有准备好时,如果工作container停止,它将被重新启动直到它。

不久前他们已经添加了depends_onfunction 。

编辑:

从撰写版本2.1+开始,您可以将depends_onhealthcheck结合使用以实现此目的:

从文档 :

 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" 

在版本2.1之前

您仍然可以使用depends_on ,但它只影响服务启动的顺序 – 而不是在依赖服务启动之前准备就绪。

它似乎至less需要1.6.0版本。

用法看起来像这样:

 version: '2' services: web: build: . depends_on: - db - redis redis: image: redis db: image: postgres 

从文档:

表示服务之间的依赖关系,这有两个作用:

  • docker-compose up将以依赖性顺序启动服务。 在下面的例子中,db和redis将在web之前启动。
  • docker-up up SERVICE将自动包含SERVICE的依赖关系。 在下面的例子中,docker-up up web也会创build并启动db和redis。

注意:据我所知,虽然这确实设置了容器的加载顺序。 它不能保证容器内的服务实际上已经加载。

例如,你的postgres 容器可能已经启动了。 但是postgres服务本身可能仍然在容器内初始化。

你也可以把它添加到命令选项,例如。

 command: bash -c "sleep 5; start.sh" 

https://github.com/docker/compose/issues/374#issuecomment-156546513

等待一个端口,你也可以使用这样的东西

 command: bash -c "while ! curl -s rabbitmq:5672 > /dev/null; do echo waiting for xxx; sleep 3; done; start.sh" 

增加等待时间,你可以多一点:

 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" 

有一个可以使用的实用工具叫做“ docker-wait ”,可以用来等待。

用于容器开始订购使用

 depends_on: 

等待先前的容器开始使用脚本

 entrypoint: ./wait-for-it.sh db:5432 

本文将帮助您https://docs.docker.com/compose/startup-order/

您也可以通过使用netcat(使用docker-wait脚本)设置等待服务启动的端点来解决此问题。 我喜欢这种方法,因为您在docker-compose.yml仍然有一个干净的command部分,您不需要将docker-compose.yml特定的代码添加到您的应用程序中:

 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 

那么你的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 

现在在官方docker文件中logging了这一点。

PS:你应该在你的docker实例中安装netcat ,如果这个不可用的话。 为此,将其添加到您的Docker文件中:

 RUN apt-get update && apt-get install netcat-openbsd -y 
Interesting Posts