TL;DR There are a lot of snippets in the web using PostgreSQL in a Docker Compose setup. They rarely use the essential feature of healthckeck to determine whether the database server is “healthy” or not. This might (or might not) be relevant for your setup. Consider a project that runs data migration scripts as part of the startup procedure it is essential that the database is in a healthy state before firing requests to the database…
The essential part of the setup is the service postgresql
in our docker-compose.yaml
:
postgres:
image: postgres:9.6.11-alpine
ports:
- 127.0.0.1:5432:5432
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
With docker-compose ps
you can easily verify the result:
Name Command State Ports
--------------------------------------------------------------------------------------------------------------
sandbox_postgres_1 docker-entrypoint.sh postgres Up (healthy) 127.0.0.1:5432->5432/tcp
This test works well for most scenarios. It was Markus who came up with an improved version of this health check. Let’s wait until a given database (sonar in this case) has been created:
psql -U sonar -lqt | cut -d \| -f 1 | grep -wq sonar
In case you are a bit puzzled (like I was on first sight) - here are the links to explainshell:
Don’t forget to quote correctly when putting the check into your docker-compose.yaml
:
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres && psql -lqt | cut -d \\| -f 1 | grep -qw sonar"]
Create the initial database
When firing up the container all scripts (*.sql
or *.sh
) in /docker-entrypoint-initdb.d
will be executed.
A base shell script creating a database could look like follows:
#!/usr/bin/env bash
set -e
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" <<-EOSQL
CREATE USER sonarqube with superuser password 's3cr3t';
CREATE DATABASE sonar;
GRANT ALL PRIVILEGES ON DATABASE sonar TO sonarqube;
EOSQL
Use the service postgres
So far so good, but…
Note: Version 3 no longer supports the condition form of depends_on
How do we configure the consuming service to wait until the database is ”healthy”?
startup-order comes with a PostgreSQL example to the rescue.
The wait-for-postgres.sh
can be used in the entrypoint
of the consuming service like follows
entrypoint: ["/wait-for-postgres.sh", "postgres", "./bin/run.sh"]
Note: This solution requires
psql
installed in the dependent container.