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
执行此操作,以等待所有必需的服务在那里。
在Dockerfile
的CMD
你可以引用你自己的启动脚本来启动你的容器服务。 在你开始之前,你需要等待一个依赖的:
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-stopped
或restart: always
可以解决这个问题。
当rabbitMQ没有准备好时,如果工作container
停止,它将被重新启动直到它。
不久前他们已经添加了depends_on
function 。
编辑:
从撰写版本2.1+开始,您可以将depends_on
与healthcheck
结合使用以实现此目的:
从文档 :
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
您也可以通过使用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