Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Waiting for a Docker container to be ready

I have the following docker-compose.yml:

version: '2'
services:
  server:
    build: .
    command: ["./setup/wait-for-postgres.sh", "tide_server::5432", "cd /app", "npm install", "npm run start"]
    ports:
      - 3030:3030
    links:
      - database
    depends_on:
      - database
  database:
    image: postgres
    environment:
      - "POSTGRES_USER=postgres"
      - "POSTGRES_PASSWORD=postgres"
      - "POSTGRES_DB=tide_server"
    ports:
      - 5432:5432

I tried following this tutorial and using the following shell script to determine when postgres is ready.

#!/bin/bash
# wait-for-postgres.sh

set -e

host="$1"
shift
cmd="$@"

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

>&2 echo "Postgres is up - executing command"
exec $cmd

My node Dockerfile is minimal but I have added it for reference:

FROM node:latest

ADD . /app

WORKDIR /app

EXPOSE 3030

Now when I try to run docker-compose up I get the following (after the postgres container is ready:

server_1    | Postgres is unavailable - sleeping
server_1    | ./setup/wait-for-postgres.sh: line 10: psql: command not found
server_1    | Postgres is unavailable - sleeping
server_1    | ./setup/wait-for-postgres.sh: line 10: psql: command not found
server_1    | Postgres is unavailable - sleeping
server_1    | ./setup/wait-for-postgres.sh: line 10: psql: command not found
server_1    | Postgres is unavailable - sleeping
server_1    | ./setup/wait-for-postgres.sh: line 10: psql: command not found

Now I am not sure if this is a linking issue, or something wrong with my script but I have tried every variation I can think of and have had no luck getting this up/

like image 311
Otis Wright Avatar asked Jan 04 '23 00:01

Otis Wright


2 Answers

This will successfully wait for Postgres to start. (Specifically line 6)

services:
  practice_docker: 
    image: dockerhubusername/practice_docker
    ports: 
      - 80:3000
    command: bash -c 'while !</dev/tcp/db/5432; do sleep 1; done; npm start'
    depends_on:
      - db
    environment:
      - DATABASE_URL=postgres://postgres:password@db:5432/practicedocker
      - PORT=3000   
  db:
    image: postgres
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=password
      - POSTGRES_DB=practicedocker
like image 100
Alister Avatar answered Jan 11 '23 22:01

Alister


When you declare command in docker-compose.yml, the command itself is executed in the container it is declared to start in. Catch my drift?

Your ./setup/wait-for-postgres.sh is being executed in the container, which has no postgres installed. And you can't change it.

But no, actually you can. Run your script in the postgres container. But if you define command in the database section, it will override the default CMD defined in postgres:latest, which is just CMD ["postgres"].

This means, you have to slightly rewrite your script:

#!/bin/bash
# wait-for-postgres.sh

set -e

host="$1"
shift
cmd="$@"

postgres

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

>&2 echo "Postgres is up - executing command"
exec $cmd
like image 27
Alex Karshin Avatar answered Jan 11 '23 22:01

Alex Karshin