'How to make container wait for other container in Docker Compose

I'm following this tutorial and try to start the infrastructure using Docker Compose instead of shell scripts calling docker client. Everything works fine, except gitlab container is started before gitlab-postgreql and gitlab-redis, thus failing, as it expects those services be already running.

I tried to use depends_on attributes, but it didn't solve the problem. As far as I know, it doesn't help, if other containers are faster to start. After a research I figured out, Docker Compose doesn't provide out-of-the-box solution to control container creation order.

How can this be? I can't believe such a fundamental feature have left unimplemented. Seems like Docker is stumbling on it's own cleverness and forgets the basics. Now, how do I control the container creation order without some crazy support scripts (which would make whole configuration more cluttered than just using scripts / docker client for everything in the first place)

Here is the docker-compose.yml as it is

version: '2'
services:

  gitlab-postgresql:
    image: sameersbn/postgresql:9.4-3
    volumes:
      - /srv/docker/gitlab/postgresql:/var/lib/postgresql
    environment:
      - DB_NAME=gitlabhq_production
      - DB_USER=gitlab
      - DB_PASS=password

  gitlab-redis:
    image: sameersbn/redis:latest
    volumes:
      - /srv/docker/gitlab/redis:/var/lib/redis
    depends_on:
      - "gitlab-postgresql"

  gitlab:
    image: sameersbn/gitlab:7.14.3
    volumes:
      - /srv/docker/gitlab/gitlab:/home/git/data
    ports:
      - "2222:22"
      - "8080:80"
    environment:
      - GITLAB_PORT=8080
      - GITLAB_SSH_PORT=2222
    depends_on:
      - gitlab-postgresql
      - gitlab-redis

  registry:
    image: registry:2
    volumes:
      - /srv/docker/registry/data:/var/lib/registry
    ports:
      - "5000:5000"
    depends_on:
      - "gitlab"

  jenkins:
    image: jenkins:1.609.3
    volumes:
      - /srv/docker/jenkins/home:/var/jenkins_home
      - /var/run/docker.sock:/var/run/docker.sock
      - /usr/bin/docker:/bin/docker
      - /usr/lib/x86_64-linux-gnu/libapparmor.so.1.1.0:/lib/x86_64-linux-gnu/libapparmor.so.1
    ports:
      - "8081:8080"
      - "50000:50000"
    user: root
    depends_on:
      - "registry"


Solution 1:[1]

gitlab container is started before gitlab-postgreql and gitlab-redis,

You are using depends_on which wait until docker container status is not "up", but every service or program within this container can be "not finished" or in statuses like "run" or "up".

Check Controlling startup order in Compose I think it is exactly what you need.

Use a tool such as wait-for-it or dockerize. These are small wrapper scripts which you can include in your application’s image and will poll a given host and port until it’s accepting TCP connections. Supposing your application’s image has a CMD set in its Dockerfile, you can wrap it by setting the entrypoint in docker-compose.yml:

So you will need entrypoint that will wait after postgres port will be available and postgres in running status. In docker-compose you will need for example entrypoint: ./wait-for-it.sh db:5432

and in the script you will check every second whether postgres is running - docker container will be blocked until postgres is unavailable.

Like in documentation:

until psql -h "$host" -U "postgres" -c '\l'; do
  >&2 echo "Postgres is unavailable - sleeping"
  sleep 1
done

Solution 2:[2]

You can use depends_on with healthcheck if using compose v2.1+ (but not 3+ as it dropped condition https://github.com/peter-evans/docker-compose-healthcheck/issues/3)

Example on GitHub

Example, in a database container:

healthcheck:
  test: ["CMD-SHELL", "pg_isready -U postgres"]
  interval: 30s
  timeout: 30s
  retries: 3

Project that depends on database:

depends_on:
  kong-database:
    condition: service_healthy

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Taylor D. Edmiston
Solution 2