我在这里使用rabbitmq和一个简单的python示例
和docker-compose一起。我的问题是我需要等待rabbitmq完全启动。从我搜索到目前为止,我不知道如何等待容器x(在我的case worker)直到y (rabbitmq)启动。
我发现了一篇他检查另一个主机是否在线的博客文章。
我还发现了这个docker命令:
等待
用法:docker wait CONTAINER[容器…]
阻塞直到容器停止,然后打印它的退出代码。
等着一个集装箱停下来也许不是我想要的,但如果
是否可以在docker-compose。yml中使用这个命令?
到目前为止,我的解决方案是等待几秒钟并检查端口,但这是实现这一点的方法吗?如果我不等待,就会得到一个错误。
docker-compose.yml
worker:
build: myapp/.
volumes:
- myapp/.:/usr/src/app:ro
links:
- rabbitmq
rabbitmq:
image: rabbitmq:3-management
Python hello sample (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 for worker:
FROM python:2-onbuild
RUN ["pip", "install", "pika"]
CMD ["python","rabbit.py"]
2015年11月更新:
在程序中使用shell脚本或等待可能是一种解决方案。但是在看到这个问题后,我正在寻找docker/docker-compose本身的命令或功能。
他们提到了实现运行状况检查的解决方案,这可能是最佳选择。一个开放的tcp连接并不意味着你的服务已经准备好或可能保持准备状态。除此之外,我需要改变我的入口点在我的dockerfile。
因此,我希望通过docker-compose on board命令得到一个答案,如果他们完成了这个问题,就有希望出现这种情况。
2016年3月更新
有人提议提供一种内置的方法来确定容器是否“活”。因此,docker-compose在不久的将来可能会得到应用。
2016年6月更新
健康检查似乎将在1.12.0版本集成到docker中
2017年1月更新
我找到了一个docker-compose解决方案,见:
Docker在启动Y之前撰写等待容器X
最后用docker-compose方法找到了解决方案。由于docker-compose文件格式2.1,您可以定义healthchecks。
我在一个例子中做过
您至少需要安装docker 1.12.0+。
我还需要扩展rabbitmq-management Dockerfile,因为curl没有安装在官方映像上。
现在我测试rabbitmq-container的管理页面是否可用。如果curl以exitcode 0结束,容器应用程序(python pika)将启动并发布消息到hello队列。它现在工作(输出)。
Docker-compose(2.1版):
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
Dockerfile (rabbitmq + curl):
FROM rabbitmq:3-management
RUN apt-get update
RUN apt-get install -y curl
EXPOSE 4369 5671 5672 25672 15671 15672
版本3不再支持depends_on的条件形式。
所以我从depends_on移动到restart -failure。现在我的应用容器将重新启动2-3次,直到它工作,但它仍然是一个docker-compose特性,没有覆盖入口点。
Docker-compose(版本3):
version: "3"
services:
rabbitmq: # login guest:guest
image: rabbitmq:management
ports:
- "4369:4369"
- "5671:5671"
- "5672:5672"
- "25672:25672"
- "15671:15671"
- "15672:15672"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:15672"]
interval: 30s
timeout: 10s
retries: 5
app:
build: ./app/
environment:
- HOSTNAMERABBIT=rabbitmq
restart: on-failure
depends_on:
- rabbitmq
links:
- rabbitmq
尝试了许多不同的方法,但喜欢这个简单的:https://github.com/ufoscout/docker-compose-wait
你可以在docker compose文件中使用ENV变量来提交一个服务主机列表(带端口),应该像这样“等待”:WAIT_HOSTS: postgres:5432, mysql:3306, mongo:27017。
假设你有下面的docker-compose。yml文件(从repo README复制/过去):
version: "3"
services:
mongo:
image: mongo:3.4
hostname: mongo
ports:
- "27017:27017"
postgres:
image: "postgres:9.4"
hostname: postgres
ports:
- "5432:5432"
mysql:
image: "mysql:5.7"
hostname: mysql
ports:
- "3306:3306"
mySuperApp:
image: "mySuperApp:latest"
hostname: mySuperApp
environment:
WAIT_HOSTS: postgres:5432, mysql:3306, mongo:27017
接下来,为了让服务等待,你需要在你的Dockerfile中添加以下两行(在服务的Dockerfile中,它应该等待其他服务启动):
ADD https://github.com/ufoscout/docker-compose-wait/releases/download/2.5.0/wait /wait
RUN chmod +x /wait
Dockerfile的完整示例(同样来自项目repo README):
FROM alpine
## Add your application to the docker image
ADD MySuperApp.sh /MySuperApp.sh
## Add the wait script to the image
ADD https://github.com/ufoscout/docker-compose-wait/releases/download/2.5.0/wait /wait
RUN chmod +x /wait
## Launch the wait tool and then your application
CMD /wait && /MySuperApp.sh
有关可能使用的其他详细信息,请参阅README
I currently also have that requirement of waiting for some services to be up and running before others start. Also read the suggestions here and on some other places. But most of them require that the docker-compose.yml some how has to be changed a bit.
So I started working on a solution which I consider to be an orchestration layer around docker-compose itself and I finally came up with a shell script which I called docker-compose-profile.
It can wait for tcp connection to a certain container even if the service does not expose any port to the host directy. The trick I am using is to start another docker container inside the stack and from there I can (usually) connect to every service (as long no other network configuration is applied).
There is also waiting method to watch out for a certain log message.
Services can be grouped together to be started in a single step before another step will be triggered to start.
You can also exclude some services without listing all other services to start (like a collection of available services minus some excluded services).
This kind of configuration can be bundled to a profile.
There is a yaml configuration file called dcp.yml which (for now) has to be placed aside your docker-compose.yml file.
对于你的问题,这看起来像:
command:
aliases:
upd:
command: "up -d"
description: |
Create and start container. Detach afterword.
profiles:
default:
description: |
Wait for rabbitmq before starting worker.
command: upd
steps:
- label: only-rabbitmq
only: [ rabbitmq ]
wait:
- 5@tcp://rabbitmq:5432
- label: all-others
现在可以通过调用来启动堆栈
dcp -p default upd
或者仅仅通过
dcp
因为只有一个默认配置文件可以运行-d。
有个小问题。我目前的版本不支持特殊的等待条件,如ony
你实际上需要。这样就没有测试给兔子发信息了。
我已经在考虑进一步的等待方法,以在主机上或作为docker容器运行某个命令。
我们可以扩展这个工具,比如
...
wait:
- service: rabbitmq
method: container
timeout: 5
image: python-test-rabbit
...
有一个名为python-test-rabbit的docker映像来进行检查。
这样做的好处是,你再也不需要把等待的部分交给你的员工了。
它将被隔离,并停留在业务流程层内。
也许有人会觉得这个有用。欢迎提出任何建议。
您可以在https://gitlab.com/michapoe/docker-compose-profile上找到这个工具