Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

fig up: docker containers start synchronisation

For one of my home projects I decided to use docker containers and fig for orchestration (first time using those tools).

Here is my fig.yaml:

rabbitmq:
  image: dockerfile/rabbitmq:latest
mongodb:
  image: mongo
app:
  build: .
  command: python /code/app/main.py
  links:
   - rabbitmq
   - mongodb
  volumes:
   - .:/code

Rabbitmq starting time is much slower than loading time of my application. Even though rabbitmq container starts loading first (since it is in app links), when my app tries to connect to rabbitmq server it's not yet available (it's definately loading timing problem, since if I just insert sleep for 5 seconds before connecting to rabbitmq - everything works fine). Is there some standard way to resolve loading time synchronisation problems?

Thanks.

like image 669
Jener Avatar asked Dec 27 '14 19:12

Jener


People also ask

How do I up the docker container?

The docker compose up command aggregates the output of each container (like docker compose logs --follow does). When the command exits, all containers are stopped. Running docker compose up --detach starts the containers in the background and leaves them running.

How do you start a container and keep it running?

Dockerfile Command to Keep the Container Running Method 1: You can use the -t (pseudo-tty) docker parameter to keep the container running. Method 2: You can run the container directly passing the tail command via arguments as shown below. Method 3: Another method is to execute a sleep command to infinity.


1 Answers

I don't think there is an standard way to solve this, but it is a known problem and some people have acceptable workarounds.

There is a proposal on the Docker issue tracker about not considering a container as started until it is listening at the exposed ports. However it likely won't be accepted due to other problems it would create elsewhere. There is a fig proposal on the same topic as well.

The easy solution is to do the sleep like @jcortejoso says. An example from http://blog.chmouel.com/2014/11/04/avoiding-race-conditions-between-containers-with-docker-and-fig/:

function check_up() {
    service=$1
    host=$2
    port=$3

    max=13 # 1 minute

    counter=1
    while true;do
        python -c "import socket;s = socket.socket(socket.AF_INET, socket.SOCK_STREAM);s.connect(('$host', $port))" \
        >/dev/null 2>/dev/null && break || \
        echo "Waiting that $service on ${host}:${port} is started (sleeping for 5)"

        if [[ ${counter} == ${max} ]];then
            echo "Could not connect to ${service} after some time"
            echo "Investigate locally the logs with fig logs"
            exit 1
        fi

        sleep 5

        (( counter++ ))
    done
}

And then use check_up "DB Server" ${RABBITMQ_PORT_5672_TCP_ADDR} 5672 before starting your app server, as described in the link above.

Another option is to use docker-wait. In your fig.yml.

rabbitmq:
  image: dockerfile/rabbitmq:latest
mongodb:
  image: mongo
rabbitmqready:
  image: aanand/wait
  links:
   - rabbitmq
app:
  build: .
  command: python /code/app/main.py
  links:
   - rabbitmqready
   - mongodb
  volumes:
   - .:/code
like image 158
dukebody Avatar answered Oct 06 '22 23:10

dukebody