Dealing with linked containers dependency in docker-compose

In docker-compose a common problem is starting services and daemons in containers that depends on services running on linked containers, in example: your app depends on elasticsearch but it is not ready when the app container is started. Solution is to use a wait script.

I knew that docker-compose team is working on adding a WAIT parameter, but while it is not ready we can use a wait script to load our services.

The process is simple, your container will execute a shell script that will try to execute a HEALTH CHECK many times you want before starting the main command. The health check, the command, the sleep and how many loops to try will be defined in environment variables

This is a program that needs to access an elasticsearch server located in ‘elastic’ host (that will be mapped by compose

access_elastic_search.py

from datetime import datetime 
from elasticsearch import Elasticsearch
es = Elasticsearch('elastic')
es.index(index="my-index", doc_type="test-type", id=42, body={"any": "data", "timestamp": datetime.now()})
print es.get(index="my-index", doc_type="test-type", id=42)

docker-compose.yml

elastic:
    image: elasticsearch
    command: elasticsearch -Des.node.name="YourNodeName"
    ports:
       - "9200:9200"

app:
    image: ubuntu:14.04
    command: wait_to_start
    working_dir: /src
    links:
        - elastic:elastic
    volumes:
        - .:/src
    environment:
        - WAIT_COMMAND=[ $(curl --write-out %{http_code} --silent --output /dev/null http://elastic:9200/_cat/health?h=st) = 200 ]
        - WAIT_START_CMD=python access_elastic_search.py
        - WAIT_SLEEP=2
        - WAIT_LOOPS=10

wait_to_start script

 #!/bin/bash

echo $WAIT_COMMAND
echo $WAIT_START_CMD

is_ready() {
    eval "$WAIT_COMMAND"
}

# wait until is ready
i=0
while ! is_ready; do
    i=`expr $i + 1`
    if [ $i -ge $WAIT_LOOPS ]; then
        echo "$(date) - still not ready, giving up"
        exit 1
    fi
    echo "$(date) - waiting to be ready"
    sleep $WAIT_SLEEP
done

#start the script
exec $WAIT_START_CMD

Now when you start your environment with docker-compose up the app container will start and execute wait_to_start script, which will perform the test defined in WAIT_COMMAND environment variable and will retry until the test succeeds, so it will end executing the program defined in WAIT_START_CMD

Full code on gist: https://gist.github.com/rochacbruno/bdcad83367593fd52005

This code was made with StackOverflow help