Docker - check if postgres is ready

Viewed 31336

I have a Kong API Gateway container and a postgres container and I need to check whether postgres has started up and ready from the Kong container before running the migrations. I was thinking of installing the postgres client utilities into a custom image based on the official Kong image using RUN yum install postgresql -y && yum clean all in my Dockerfile and using either psql or pg_isready to achieve this. I've created a postgres user called polling with an empty password specifically for checking the status of the server by these two utilities. Neither of them work.

I tried to execute these commands from the custom Kong image:

  1. psql. The command psql -h postgres -U polling -w -c '\l' fails with the error psql: fe_sendauth: no password supplied. But the user has no password. What am I doing wrong? The full shell script checking whether the server is ready using psql is described here.

  2. pg_isready. I don't get how to install this utility separately into a custom image based on the official Kong image which in turn based on the centos:7 image, the postgresql package doesn't include pg_isready. Only these utilities are installed and can be found in /usr/bin: pg_config, pg_dump, pg_dumpall, pg_restore, psql. How to install pg_isready? I don't want to have the full server installation in the Kong image.

4 Answers

Here is a shell one liner using pg_isready tool provided by PostgreSQL.

To call outside docker:

DOCKER_CONTAINER_NAME="mypgcontainer"
timeout 90s bash -c "until docker exec $DOCKER_CONTAINER_NAME pg_isready ; do sleep 5 ; done"

Based on a post from Jeroma Belleman.

I tried wait-for-it, but it may be a problem to run it in docker container as in the docker image may not be installed nc (sometimes there is not even ping, telnet, curl..). So to check if the DB is up and running I have used HealthCheck in docker compose file what was checking return value of pg_isready, what is part of postgres database, so you do not need to install anything into docker images:

version: '2.3'
services:
  postgres-db:
    image: postgresImage
    healthcheck:
      test: /usr/bin/pg_isready
      interval: 5s
      timeout: 10s
      retries: 120
    ports:
      - '5432:5432'

  aplication:
    image: applicationImage
    depends_on:
      postgres-db:
        condition: service_healthy

We solve this with a simple TCP check on port 5432, without any PG tooling. We just use wait-for-it.sh, and it works well. Postgres does not open the port until the server is actually ready to serve, so this is apparently fine.

Sample Dockerfile: https://github.com/apim-haufe-io/wicked.kong/blob/master/Dockerfile

Corresponding start script (only the last line is interesting for this specific problem): https://github.com/apim-haufe-io/wicked.kong/blob/master/startup.sh

Snippet:

wait-for-it.sh -h $KONG_PG_HOST -p 5432 -t 30 -- kong start --run-migrations

Wait for it: https://github.com/vishnubob/wait-for-it

My solution was to create a new image based on the official kong image and override the entrypoint like this:

#!/usr/bin/env bash
set -e

# Disabling nginx daemon mode
export KONG_NGINX_DAEMON="off"

# Setting default prefix (override any existing variable)
export KONG_PREFIX="/usr/local/kong"

# Prepare Kong prefix
if [ "$1" = "/usr/local/openresty/nginx/sbin/nginx" ]; then
    kong prepare -p "/usr/local/kong"
fi

#waiting for postgres
until psql --host=$KONG_PG_HOST --username=$POLLING_USER $POLLING_DATABASE -w &>/dev/null
do
  echo "Waiting for PostgreSQL..."
  sleep 1
done

echo "Postgres is ready, running the migrations..."

kong migrations up

echo "READY TO START UP KONG USING CMD" $@;

exec "$@"
Related