Skip to content

Commit

Permalink
Latest stable changes from develop with support for PostgreSQL 12.2 (#1)
Browse files Browse the repository at this point in the history
* Initial revision

* Updated docker image to user PostgreSQL 12 and Java 11.

* Made Dockerfile compatible with previous versions of the base image. e.g. postgres:1X-alpine

* Added link to question about sending the output of the Docker build to the console.

* Removed --version hack from the RUN command used to create the database.  See docker-library/postgres#718 for more details.

* Added custom entry point.

* Updated flyway configuration files and changed entry point to prevent silent migration failures.
  • Loading branch information
doraemoncito authored Apr 27, 2020
1 parent 219800c commit f0d14c5
Show file tree
Hide file tree
Showing 9 changed files with 1,006 additions and 25 deletions.
26 changes: 3 additions & 23 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,23 +1,3 @@
# Compiled class file
*.class

# Log file
*.log

# BlueJ files
*.ctxt

# Mobile Tools for Java (J2ME)
.mtj.tmp/

# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
.idea/
target/
*.iml
62 changes: 60 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,60 @@
# postgresql
Containerised PostgreSQL database with flyway baked-in
# PostgreSQL database with embedded schema migrator

Docker image containing a PostgreSQL database and a schema migrator to simplify database schema upgrades.

## Building the Docker image

### Using the Maven command line:

```shell script
mvn clean install
```

### Using the Docker command line:
From the top-level directory, run the following command to copy the build assets to the target directory:

```shell script
mvn compile
```

Then go to the target directory and invoke Docker build as shown here:

```shell script
pushd target/docker
docker build . --tag localhost.localdomain/postgresql-container:latest --no-cache
popd
```

## Running the database

Use the following command to the start the Database in a background docker container:

```shell script
docker run -p 5432:5432 --name postgres -d localhost.localdomain/postgresql-container:latest
```

## Connecting to the database

Use the following JDBC URL to connect to the database:

```text
jdbc:postgresql://localhost:5432/postgres
```
## Extending the database schema

To extend the schema definition with the tables, data, etc, simply add new idempotent SQL scripts to the
`src/main/resources/db/migration/` folder.

The SQL script file names must follow the pattern
`SPRINT<zero padded three digit sprint number>_<zero padded two digit script order number>__<description>.sql`
as shown in this example: `SPRINT001_01__Initial_database_revision.sql`.

## Resources

- [PostgreSQL](https://www.postgresql.org)
- [Flyway](https://flywaydb.org)
- [postgres - Docker Official Images](https://hub.docker.com/_/postgres)
- [Docker Library PostgreSQL on GitHub](https://github.com/docker-library/postgres)
- ["exec: \"docker-entrypoint.sh\": executable file not found in $PATH". #296](https://github.com/docker-library/postgres/issues/296)
- [Sending RUN ["docker-entrypoint.sh", "postgres", "--version"] output to the console during the build #718](https://github.com/docker-library/postgres/issues/718)
- [Functionalize the entrypoint to allow outside sourcing for extreme customizing of startup #496](https://github.com/docker-library/postgres/pull/496)
167 changes: 167 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.doraemoncito</groupId>
<artifactId>postgresql-container</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>PostgreSQL container</name>
<description>PostgreSQL database bound with flyway and encapsulated in a docker container</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

<java.version>11</java.version>
<maven.version>3.6.0</maven.version>

<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>

<docker.registry.url>localhost.localdomain</docker.registry.url>
<docker.image.name>${docker.registry.url}/${project.artifactId}</docker.image.name>
<docker.pull.on.build>true</docker.pull.on.build>

<dockerfile-maven-plugin.version>1.4.13</dockerfile-maven-plugin.version>
<maven-dependency-plugin.version>3.1.2</maven-dependency-plugin.version>
<maven-resources-plugin.version>3.1.0</maven-resources-plugin.version>

<flyway-commandline.version>6.3.3</flyway-commandline.version>
</properties>
<dependencies>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-commandline</artifactId>
<version>${flyway-commandline.version}</version>
<classifier>linux-x64</classifier>
<type>tar.gz</type>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>${maven-dependency-plugin.version}</version>
<executions>
<execution>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-commandline</artifactId>
<version>${flyway-commandline.version}</version>
<classifier>linux-x64</classifier>
<type>tar.gz</type>
<outputDirectory>${project.build.directory}/docker</outputDirectory>
<overWrite>false</overWrite>
</artifactItem>
</artifactItems>
<stripClassifier>true</stripClassifier>
<stripVersion>true</stripVersion>
<overWriteIfNewer>true</overWriteIfNewer>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>${maven-resources-plugin.version}</version>
<executions>
<execution>
<id>copy-scripts</id>
<phase>generate-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/docker</outputDirectory>
<overwrite>true</overwrite>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>db/**</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
<execution>
<id>copy-docker</id>
<phase>generate-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/docker</outputDirectory>
<overwrite>true</overwrite>
<resources>
<resource>
<directory>${project.basedir}/src/main/docker</directory>
<includes>
<include>**</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>${dockerfile-maven-plugin.version}</version>
<configuration>
<repository>${docker.image.name}</repository>
<dockerfile>${project.build.directory}/docker/Dockerfile</dockerfile>
<contextDirectory>${project.build.directory}/docker</contextDirectory>
<tag>${project.version}</tag>
<!-- NOTE: dockerfile-maven-plugin does not appear to be able to tag the same image with multiple labels-->
<!-- <tag>latest</tag>-->
<!-- skip writing the test metadata to ${project.build.directory}/docker or copy the resources to -->
<!-- a directory other than ${project.build.directory}/docker because the dockerfile-maven-plugin -->
<!-- itself uses that directory to write metadata that that conflicts with the build. -->
<!-- See https://github.com/spotify/dockerfile-maven/issues/75 for more details. -->
<writeTestMetadata>false</writeTestMetadata>
</configuration>
<executions>
<!-- Build the docker image using the Maven project version as the tag -->
<execution>
<id>build</id>
<phase>package</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
<!-- Tag the newly built docker image using the 'latest' tag -->
<execution>
<id>tag-latest</id>
<goals>
<goal>tag</goal>
</goals>
<configuration>
<tag>latest</tag>
</configuration>
</execution>
<execution>
<id>deploy</id>
<phase>deploy</phase>
<goals>
<goal>push</goal>
</goals>
<configuration>
<tag>${project.version}</tag>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
30 changes: 30 additions & 0 deletions src/main/docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
FROM postgres:12-alpine
LABEL maintainer="jose.hernandez@bristolalumni.org.uk"
LABEL name="PostgreSQL 12 Database" vendor="Jose Hernandez"
EXPOSE 5432

RUN apk --no-cache update upgrade && apk add --no-cache openjdk11 su-exec
COPY db/ /db/
COPY entrypoint.sh /entrypoint.sh
COPY flyway-commandline.tar.gz /flyway-commandline.tar.gz

# Install the flyway schema migrator
RUN tar -pxzf flyway-commandline.tar.gz \
&& rm flyway-commandline.tar.gz \
&& mv /flyway-* /flyway \
&& rm -fr /flyway/jre \
&& chmod 777 -R /flyway /db /entrypoint.sh

# Variables required for the schema migration (i.e. flyway)
ENV PGDATA=/var/lib/postgresql-static/data \
POSTGRES_DB=postgres \
POSTGRES_USER=postgres \
POSTGRES_PASSWORD=password \
PGPORT=5432 \
# Uncomment this line to use password authentication, instead of trust, inside the container.
# Please note that using trust authentication generates the following warning in the logs:
# initdb: warning: enabling "trust" authentication for local connections
# POSTGRES_INITDB_ARGS="-A password" \
JAVA_HOME=/usr/lib/jvm/java-11-openjdk

RUN ["/entrypoint.sh", "postgres"]
66 changes: 66 additions & 0 deletions src/main/docker/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#!/bin/bash

#!/usr/bin/env bash
set -Eeo pipefail

# Example using the functions of the postgres entry point to customize startup to always run files in /always-initdb.d/

source "$(which docker-entrypoint.sh)"

docker_setup_env
docker_create_db_directories
# assumption: we are already running as the owner of PGDATA

# This is needed if the container is started as `root`
if [ "$1" = 'postgres' ] && [ "$(id -u)" = '0' ]; then
exec su-exec postgres "$BASH_SOURCE" "$@"
fi

echo "Running flyway to update the PostgreSQL database"
PATH=$PATH:/flyway

echo "============================================================"
echo " PATH: ${PATH}"
echo " PGDATA: ${PGDATA}"
echo " POSTGRES_DB: ${POSTGRES_DB}"
echo " POSTGRES_USER: ${POSTGRES_USER}"
echo " PGPORT: ${PGPORT}"
echo "POSTGRES_INITDB_ARGS: ${POSTGRES_INITDB_ARGS}"
echo "============================================================"

if [ -z "$DATABASE_ALREADY_EXISTS" ]; then
docker_verify_minimum_env
docker_init_database_dir
pg_setup_hba_conf

# only required for '--auth[-local]=md5' on POSTGRES_INITDB_ARGS
export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}"

docker_temp_server_start "$@" -c max_locks_per_transaction=256
docker_setup_db

# Ensure that PostgreSQL is restarted after the authentication is set to trust instead of ident so that flyway can
# connect to the database to perform migration. For more details please visit the PostgreSQL documentation page at
# https://www.postgresql.org/docs/11/client-authentication.html
pg_ctl --options "-c listen_addresses='localhost'" --wait restart

/flyway/flyway -user="$POSTGRES_USER" -password="$POSTGRES_PASSWORD" -configFiles=/db/configuration/postgres/flyway.properties -url="jdbc:postgresql://localhost:$PGPORT/$POSTGRES_DB?user=$POSTGRES_USER" -locations="filesystem:/db/migration" info migrate info || exit 1

docker_process_init_files /docker-entrypoint-initdb.d/*

docker_temp_server_stop
else
docker_temp_server_start "$@"

# Ensure that PostgreSQL is restarted after the authentication is set to trust instead of ident so that flyway can
# connect to the database to perform migration. For more details please visit the PostgreSQL documentation page at
# https://www.postgresql.org/docs/11/client-authentication.html
pg_ctl --options "-c listen_addresses='localhost'" --wait restart

/flyway/flyway -user="$POSTGRES_USER" -password="$POSTGRES_PASSWORD" -configFiles=/db/configuration/postgres/flyway.properties -url="jdbc:postgresql://localhost:$PGPORT/$POSTGRES_DB?user=$POSTGRES_USER" -locations="filesystem:/db/migration" info migrate info || exit 1

docker_process_init_files /always-initdb.d/*
docker_temp_server_stop
fi

echo "entrypoint.sh Completed"
Loading

0 comments on commit f0d14c5

Please sign in to comment.