I am using rabbitmq and a simple python sample from here together with docker-compose. My problem is that I need to wait for rabbitmq to be fully started. From what I searched so far, I don't know how to wait with container x (in my case worker) until y (rabbitmq) is started.
I found this blog post where he checks if the other host is online. I also found this docker command:
wait
Usage: docker wait CONTAINER [CONTAINER...]
Block until a container stops, then print its exit code.
Waiting for a container to stop is maybe not what I am looking for but if it is, is it possible to use that command inside the docker-compose.yml? My solution so far is to wait some seconds and check the port, but is this the way to achieve this? If I don't wait, I get an error.
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"]
Update Nov 2015:
A shell script or waiting inside your program is maybe a possible solution. But after seeing this Issue I am looking for a command or feature of docker/docker-compose itself.
They mention a solution for implementing a health check, which may be the best option. A open tcp connection does not mean your service is ready or may remain ready. In addition to that I need to change my entrypoint in my dockerfile.
So I am hoping for an answer with docker-compose on board commands, which will hopefully the case if they finish this issue.
Update March 2016
There is a proposal for providing a built-in way to determine if a container is "alive". So docker-compose can maybe make use of it in near future.
Update June 2016
It seems that the healthcheck will be integrated into docker in Version 1.12.0
Update January 2017
I found a docker-compose solution see: Docker Compose wait for container X before starting Y
Start a container in the background. Run docker wait , which should block until the container exits. In another terminal, stop the first container. The docker wait command above returns the exit code.
Starting a docker container The syntax of the docker run command is as follows: $ docker run [OPTIONS] IMAGE[:TAG|@DIGEST] [COMMAND] [ARG...] The command takes the image name, with the optional TAG or DIGEST.
Like the restart Docker command, Docker Compose includes the restart property to restart containers automatically. We can also define restart policies in Docker Compose by providing the restart property to the service in the docker-compose. yml file.
The 'docker wait' is a command that is used to wait or block until one or more containers stop, and then it outputs their exit codes which means you cannot use your terminal if you are running the command on the terminal.
Finally found a solution with a docker-compose method. Since docker-compose file format 2.1 you can define healthchecks.
I did it in a example project you need to install at least docker 1.12.0+. I also needed to extend the rabbitmq-management Dockerfile, because curl isn't installed on the official image.
Now I test if the management page of the rabbitmq-container is available. If curl finishes with exitcode 0 the container app (python pika) will be started and publish a message to hello queue. Its now working (output).
docker-compose (version 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
output:
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
Version 3 no longer supports the condition form of depends_on. So i moved from depends_on to restart on-failure. Now my app container will restart 2-3 times until it is working, but it is still a docker-compose feature without overwriting the entrypoint.
docker-compose (version 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
Natively that is not possible, yet. See also this feature request.
So far you need to do that in your containers CMD
to wait until all required services are there.
In the Dockerfile
s CMD
you could refer to your own start script that wraps starting up your container service. Before you start it, you wait for a depending one like:
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
Probably you need to install netcat in your Dockerfile
as well. I do not know what is pre-installed on the python image.
There are a few tools out there that provide easy to use waiting logic, for simple tcp port checks:
For more complex waits:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With