Postgres Docker image with Flyway migrations for integration testing

Last update on 03/2023

Here's how you set up a Docker image of a PostgreSQL database with migrations (and possibly test data) applied by Flyway - often for integration testing.

Source on GitHub

Assume following folder structure:


Ensure to do a sudo chmod a+x The content of the shell script:

set -o errexit
set -o pipefail
set -o nounset

flyway -jdbcProperties.socketFactory='$FactoryArg' -jdbcProperties.socketFactoryArg=/var/run/postgresql/.s.PGSQL.5432 -jdbcProperties.sslMode=disable migrate

Order of things are important, don't try to change anything.

We must switch out the class responsible for connecting to Postgres because during startup of the temporary database only unix sockets and no TCP is available. For this purpose we will later download a specific driver.

The flyway.conf I'm going to use is unspectacular:


And finally the Dockerfile:

# I'll use PostGIS as base image but you can also do this with the official one.
FROM postgis/postgis:13-master

# We download Flyway and install it, nothing special.
ADD /flyway.tar.gz
RUN tar xvf /flyway.tar.gz
RUN mv flyway-9.15.0 flyway
RUN chmod +x /flyway/flyway
RUN ln -s /flyway/flyway /usr/local/bin/flyway

# We download the driver for unix sockets and place it in Flyway's driver folder.
ADD /junixsocket.tar.gz
RUN tar xvf /junixsocket.tar.gz
RUN mv /junixsocket-dist-2.6.2/lib/junixsocket-common-2.6.2.jar /flyway/drivers/junixsocket-common-2.6.2.jar
RUN mv /junixsocket-dist-2.6.2/lib/junixsocket-native-common-2.6.2.jar /flyway/drivers/junixsocket-native-common-2.6.2.jar

# We copy the script to the `docker-entrypoint-initdb.d`.
# Shell scripts in this folder will get executed on startup.
# Do mind the integer prefix of the file if order is important.
# I prefixed it with `20` because PostGIS uses `10` and my SQL relies on it.
COPY /docker-entrypoint-initdb.d/
RUN chmod +x /docker-entrypoint-initdb.d/

# Copy Flyway configuration
COPY flyway.conf /flyway.conf

# Copy SQL files
COPY sql /sql

For building and running nothing special is required:

docker build . -t foobar
docker run -e POSTGRES_USER=admin -e POSTGRES_PASSWORD=admin -e POSTGRES_DB=platform -p 5432:5432 foobar