From 1583c2994f7fa1a82bb8d5958327dd1e5a7f9804 Mon Sep 17 00:00:00 2001 From: Wladislaw Wagner <64201310+wlad@users.noreply.github.com> Date: Mon, 22 Mar 2021 14:30:12 +0100 Subject: [PATCH] copied from https://github.com/ehrbase/docker/pull/3 to create and push experimental docker image --- README.md | 1 - .../ehrbase-postgresql-full.dockerfile | 85 +++++++++-------- dockerfiles/scripts/chain-load.sh | 71 ++++++++++++++ dockerfiles/scripts/create-ehrbase-user.sh | 16 ++-- dockerfiles/scripts/etc/pg_hba.conf | 95 +++++++++++++++++++ dockerfiles/scripts/install-jsquery.sh | 13 --- .../scripts/install-temporal-tables.sh | 20 ---- dockerfiles/scripts/prepare-databases.sh | 26 ++--- dockerfiles/scripts/test-temporal-tables.sh | 6 ++ 9 files changed, 236 insertions(+), 97 deletions(-) create mode 100644 dockerfiles/scripts/chain-load.sh create mode 100644 dockerfiles/scripts/etc/pg_hba.conf delete mode 100644 dockerfiles/scripts/install-jsquery.sh delete mode 100644 dockerfiles/scripts/install-temporal-tables.sh create mode 100644 dockerfiles/scripts/test-temporal-tables.sh diff --git a/README.md b/README.md index 43d740d..8b7f847 100644 --- a/README.md +++ b/README.md @@ -55,4 +55,3 @@ The following parameters can be set via -e option: | POSTGRES_PASSWORD | Password for postgres | postgres | | EHRBASE_USER | Username for ehrbase user | ehrbase | | EHRBASE_PASSWORD | Password for ehrbase user | ehrbase | - diff --git a/dockerfiles/ehrbase-postgresql-full.dockerfile b/dockerfiles/ehrbase-postgresql-full.dockerfile index 9475312..80766b7 100644 --- a/dockerfiles/ehrbase-postgresql-full.dockerfile +++ b/dockerfiles/ehrbase-postgresql-full.dockerfile @@ -3,56 +3,65 @@ FROM postgres:11.5-alpine # Set default values for database user and passwords ARG EHRBASE_USER="ehrbase" ARG EHRBASE_PASSWORD="ehrbase" -ENV EHRBASE_USER=${EHRBASE_USER} -ENV EHRBASE_PASSWORD=${EHRBASE_PASSWORD} +ENV EHRBASE_USER=${EHRBASE_USER:-ehrbase} +ENV EHRBASE_PASSWORD=${EHRBASE_PASSWORD:-ehrbase} # Set Postgres data directory to custom folder ENV PGDATA="/var/lib/postgresql/pgdata" # Create custom data directory and change ownership to postgres user -RUN mkdir -p ${PGDATA} +USER root +RUN mkdir -p ${PGDATA} /usr/local/share/doc/ RUN chown postgres: ${PGDATA} RUN chmod 0700 ${PGDATA} # Define Postgres version for easier upgrades for the future ENV PG_MAJOR=11.11 -# Copy init scripts to init directory -COPY ./scripts/create-ehrbase-user.sh /docker-entrypoint-initdb.d/ +# Copy system scripts to the scripts directory on root +COPY scripts /scripts +RUN chmod +x /scripts/* + +# Install python and dependencies +RUN apk add --update postgresql=${PG_MAJOR}-r0 \ + build-base \ + git \ + flex \ + bison \ + psutils + +# Install JSQuery +RUN cd /scripts/ \ + && git clone https://github.com/postgrespro/jsquery.git \ + && cd jsquery \ + && make USE_PGXS=1 \ + && make USE_PGXS=1 install + +# Install temporal tables +RUN cd /scripts/ \ + && git clone https://github.com/mlt/temporal_tables.git --branch mlt \ + && cd temporal_tables \ + && make PGUSER=postgres \ + && make install + +# Allow regression test to run from /scripts/temporal +RUN chown -R root:postgres /scripts +RUN chmod -R g+rwx /scripts # Initialize basic database cluster -RUN sh -c "/usr/local/bin/docker-entrypoint.sh postgres & " && \ - sleep 20 && \ - echo "Database initialized" +RUN su postgres -c sh -c "/scripts/chain-load.sh SETUP" \ + && su postgres -c sh -c "/usr/local/bin/docker-entrypoint.sh postgres &" \ + && su postgres -c sh -c "/scripts/chain-load.sh WAIT" \ + && su postgres -c sh -c "/scripts/chain-load.sh SPAWNSET" \ + && su postgres -c sh -c "/scripts/chain-load.sh STOP" -# Allow connections from all adresses & Listen to all interfaces -RUN echo "host all all 0.0.0.0/0 scram-sha-256" >> ${PGDATA}/pg_hba.conf -RUN echo "listen_addresses='*'" >> ${PGDATA}/postgresql.conf +RUN echo "DONE" > /scripts/.pginit -# Install python and dependencies -RUN apk add --update postgresql=${PG_MAJOR}-r0 \ - build-base \ - git \ - flex \ - bison - -# Install temporary_tables plugin -COPY ./scripts/install-temporal-tables.sh . -RUN chmod +x ./install-temporal-tables.sh -RUN sh -c "./install-temporal-tables.sh" - -# Install jsquery plugin -COPY ./scripts/install-jsquery.sh . -RUN chmod +x ./install-jsquery.sh -RUN sh -c "./install-jsquery.sh" - -# Prepare database schemas -COPY ./scripts/prepare-databases.sh . -RUN chmod +x ./prepare-databases.sh -RUN sh -c "./prepare-databases.sh" - -# Cleanup -RUN rm -f -r ./jsquery -RUN rm -f -r ./temporal_tables - -EXPOSE 5432 +# Copy init scripts to init directory +COPY /scripts/chain-load.sh /docker-entrypoint-initdb.d/ +# COPY the pg_hba to the PGDATA directory +COPY /scripts/etc/pg_hba.conf ${PGDATA}/ +RUN echo "Enforcing ownership, one moment" \ + && chown -R postgres:postgres ${PGDATA} + +EXPOSE 5432 \ No newline at end of file diff --git a/dockerfiles/scripts/chain-load.sh b/dockerfiles/scripts/chain-load.sh new file mode 100644 index 0000000..98e96c3 --- /dev/null +++ b/dockerfiles/scripts/chain-load.sh @@ -0,0 +1,71 @@ +#!/bin/bash + +# Read in ARG0 +STARTSERVER="$1"; + +# Always swap to /scripts +cd /scripts + +# Always expand the enviroment +set -e + +# Incase this is a volume mount move +if [ -f "/scripts/.pginit" ]; then + STARTSERVER="SPAWNSET" +fi + +if [[ -z "$STARTSERVER" ]]; then + echo "No runmode specified!" + exit 0 +else + echo "Running mode: $STARTSERVER" +fi + +# If we are in setup, init the db and install the required databases +# and modules +if [ $STARTSERVER == "INIT" ]; then + sh -c 'pg_ctl initdb -D ${PGDATA}' +elif [ "$STARTSERVER" == "START" ]; then + sh -c 'pg_ctl start -D ${PGDATA}' +elif [ "$STARTSERVER" == "WAIT" ]; then + LOOPRUN=0 + while [ "$LOOPRUN" != 1 ]; do + sleep 1 + LOOPRUN=$(perl -e 'print `psql -AtXq -U postgres -d template1 -c "SELECT 1"`') + done + echo "Primary database initilization complete!" +elif [ "$STARTSERVER" == "STOP" ]; then + sh -c 'pg_ctl stop -D ${PGDATA}' +elif [ "$STARTSERVER" == "SETUP" ]; then + # Totally remove the PGDATA to force re-init on image start + rm -Rf "${PGDATA}" +elif [ "$STARTSERVER" == "SPAWNSET" ]; then + # If this is a move, then there will be no PGDATA/.spawn + if [ -f "${PGDATA}/.spawn" ]; then + exit 0; + fi + + # Execute the DB init scripts, we are already the postgres user + # Add in MD5 auth + echo "listen_addresses='*'" >> ${PGDATA}/postgresql.conf + + echo "Running temporal table test" + eval ./test-temporal-tables.sh + + echo "Running: create-ehrbase-user" + eval ./create-ehrbase-user.sh + + echo "Creating default databases" + eval ./prepare-databases.sh + + # To stop looping init + echo "DONE" > "${PGDATA}/.spawn" + echo "Restarting server" + sh -c "/scripts/chain-load.sh stop" + sh -c "/scripts/chain-load.sh start" +elif [ "$STARTSERVER" == "PASSRESET" ]; then + echo "Running: password-recrypt-set" + eval ./password-recrypt-set.sh +else + echo "Unknown action '$STARTSERVER' called." +fi; diff --git a/dockerfiles/scripts/create-ehrbase-user.sh b/dockerfiles/scripts/create-ehrbase-user.sh index 7387a83..3e17a00 100644 --- a/dockerfiles/scripts/create-ehrbase-user.sh +++ b/dockerfiles/scripts/create-ehrbase-user.sh @@ -1,12 +1,10 @@ #!/bin/bash -set -e -psql --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL - CREATE ROLE ${EHRBASE_USER} LOGIN PASSWORD '${EHRBASE_PASSWORD}'; - CREATE DATABASE ehrbase ENCODING 'UTF-8' TEMPLATE template0; - GRANT ALL PRIVILEGES ON DATABASE ehrbase TO ${EHRBASE_USER}; - CREATE USER root WITH SUPERUSER; -EOSQL +echo "Creating user(${EHRBASE_USER}) pass(${EHRBASE_PASSWORD}) db(ehrbase)" -# Stop database before proceeding -su - postgres -c "pg_ctl -D ${PGDATA} -w stop" +psql -U "${POSTGRES_USER}" -d "${POSTGRES_DB}" <<-EOSQL +CREATE ROLE ${EHRBASE_USER} WITH LOGIN PASSWORD '${EHRBASE_PASSWORD}'; +CREATE DATABASE ehrbase ENCODING 'UTF-8' TEMPLATE template0; +GRANT ALL PRIVILEGES ON DATABASE ehrbase TO ${EHRBASE_USER}; +CREATE USER root WITH SUPERUSER; +EOSQL \ No newline at end of file diff --git a/dockerfiles/scripts/etc/pg_hba.conf b/dockerfiles/scripts/etc/pg_hba.conf new file mode 100644 index 0000000..fa89804 --- /dev/null +++ b/dockerfiles/scripts/etc/pg_hba.conf @@ -0,0 +1,95 @@ +# PostgreSQL Client Authentication Configuration File +# =================================================== +# +# Refer to the "Client Authentication" section in the PostgreSQL +# documentation for a complete description of this file. A short +# synopsis follows. +# +# This file controls: which hosts are allowed to connect, how clients +# are authenticated, which PostgreSQL user names they can use, which +# databases they can access. Records take one of these forms: +# +# local DATABASE USER METHOD [OPTIONS] +# host DATABASE USER ADDRESS METHOD [OPTIONS] +# hostssl DATABASE USER ADDRESS METHOD [OPTIONS] +# hostnossl DATABASE USER ADDRESS METHOD [OPTIONS] +# +# (The uppercase items must be replaced by actual values.) +# +# The first field is the connection type: "local" is a Unix-domain +# socket, "host" is either a plain or SSL-encrypted TCP/IP socket, +# "hostssl" is an SSL-encrypted TCP/IP socket, and "hostnossl" is a +# plain TCP/IP socket. +# +# DATABASE can be "all", "sameuser", "samerole", "replication", a +# database name, or a comma-separated list thereof. The "all" +# keyword does not match "replication". Access to replication +# must be enabled in a separate record (see example below). +# +# USER can be "all", a user name, a group name prefixed with "+", or a +# comma-separated list thereof. In both the DATABASE and USER fields +# you can also write a file name prefixed with "@" to include names +# from a separate file. +# +# ADDRESS specifies the set of hosts the record matches. It can be a +# host name, or it is made up of an IP address and a CIDR mask that is +# an integer (between 0 and 32 (IPv4) or 128 (IPv6) inclusive) that +# specifies the number of significant bits in the mask. A host name +# that starts with a dot (.) matches a suffix of the actual host name. +# Alternatively, you can write an IP address and netmask in separate +# columns to specify the set of hosts. Instead of a CIDR-address, you +# can write "samehost" to match any of the server's own IP addresses, +# or "samenet" to match any address in any subnet that the server is +# directly connected to. +# +# METHOD can be "trust", "reject", "md5", "password", "scram-sha-256", +# "gss", "sspi", "ident", "peer", "pam", "ldap", "radius" or "cert". +# Note that "password" sends passwords in clear text; "md5" or +# "scram-sha-256" are preferred since they send encrypted passwords. +# +# OPTIONS are a set of options for the authentication in the format +# NAME=VALUE. The available options depend on the different +# authentication methods -- refer to the "Client Authentication" +# section in the documentation for a list of which options are +# available for which authentication methods. +# +# Database and user names containing spaces, commas, quotes and other +# special characters must be quoted. Quoting one of the keywords +# "all", "sameuser", "samerole" or "replication" makes the name lose +# its special character, and just match a database or username with +# that name. +# +# This file is read on server startup and when the server receives a +# SIGHUP signal. If you edit the file on a running system, you have to +# SIGHUP the server for the changes to take effect, run "pg_ctl reload", +# or execute "SELECT pg_reload_conf()". +# +# Put your actual configuration here +# ---------------------------------- +# +# If you want to allow non-local connections, you need to add more +# "host" records. In that case you will also need to make PostgreSQL +# listen on a non-local interface via the listen_addresses +# configuration parameter, or via the -i or -h command line switches. + +# CAUTION: Configuring the system for local "trust" authentication +# allows any local user to connect as any PostgreSQL user, including +# the database superuser. If you do not trust all your local users, +# use another authentication method. + + +# TYPE DATABASE USER ADDRESS METHOD + +# "local" is for Unix domain socket connections only +local all all trust +# IPv4 local connections: +host all all 127.0.0.1/32 trust +# IPv6 local connections: +host all all ::1/128 trust +# Allow replication connections from localhost, by a user with the +# replication privilege. +local replication all trust +host replication all 127.0.0.1/32 trust +host replication all ::1/128 trust +# Require MD5 auth for all other connections +host all all 0.0.0.0/0 md5 \ No newline at end of file diff --git a/dockerfiles/scripts/install-jsquery.sh b/dockerfiles/scripts/install-jsquery.sh deleted file mode 100644 index 4c7bed3..0000000 --- a/dockerfiles/scripts/install-jsquery.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -set -e - -# Fetch from remote repository -git clone https://github.com/postgrespro/jsquery.git -cd jsquery - -# Build jsQuery plugin -make USE_PGXS=1 && \ -make USE_PGXS=1 install && \ - -cd .. \ No newline at end of file diff --git a/dockerfiles/scripts/install-temporal-tables.sh b/dockerfiles/scripts/install-temporal-tables.sh deleted file mode 100644 index 6314eb4..0000000 --- a/dockerfiles/scripts/install-temporal-tables.sh +++ /dev/null @@ -1,20 +0,0 @@ -#!/bin/bash - -set -e - -# Start server -su - postgres -c "pg_ctl -D ${PGDATA} -w start" - -# Fetch from branch "mlt" which has full support of Postgres 11 -git clone https://github.com/mlt/temporal_tables.git --branch mlt -cd temporal_tables - -# Build from source -make PGUSER=postgres && -make install && -make installcheck - -# Stop server -su - postgres -c "pg_ctl -D ${PGDATA} -w stop" - -cd .. \ No newline at end of file diff --git a/dockerfiles/scripts/prepare-databases.sh b/dockerfiles/scripts/prepare-databases.sh index c091668..786c376 100644 --- a/dockerfiles/scripts/prepare-databases.sh +++ b/dockerfiles/scripts/prepare-databases.sh @@ -1,21 +1,15 @@ #!/bin/bash -set -e - -# Start server -su - postgres -c "pg_ctl -D ${PGDATA} -w start" +echo "Creating schemas" # Setup schemas and activate extensions psql --username="$POSTGRES_USER" --dbname "ehrbase" <<-EOSQL - CREATE SCHEMA IF NOT EXISTS ehr AUTHORIZATION "$EHRBASE_USER"; - CREATE SCHEMA IF NOT EXISTS ext AUTHORIZATION "$EHRBASE_USER"; - CREATE EXTENSION IF NOT EXISTS "uuid-ossp" SCHEMA ext; - CREATE EXTENSION IF NOT EXISTS "temporal_tables" SCHEMA ext; - CREATE EXTENSION IF NOT EXISTS "jsquery" SCHEMA ext; - CREATE EXTENSION IF NOT EXISTS "ltree" SCHEMA ext; - ALTER DATABASE ehrbase SET search_path to "$EHRBASE_USER",public,ext; - GRANT ALL ON ALL FUNCTIONS IN SCHEMA ext TO $EHRBASE_USER; -EOSQL - -# Stop server -su - postgres -c "pg_ctl -D ${PGDATA} -w stop" +CREATE SCHEMA IF NOT EXISTS ehr AUTHORIZATION "$EHRBASE_USER"; +CREATE SCHEMA IF NOT EXISTS ext AUTHORIZATION "$EHRBASE_USER"; +CREATE EXTENSION IF NOT EXISTS "uuid-ossp" SCHEMA ext; +CREATE EXTENSION IF NOT EXISTS "temporal_tables" SCHEMA ext; +CREATE EXTENSION IF NOT EXISTS "jsquery" SCHEMA ext; +CREATE EXTENSION IF NOT EXISTS "ltree" SCHEMA ext; +ALTER DATABASE ehrbase SET search_path to "$EHRBASE_USER",public,ext; +GRANT ALL ON ALL FUNCTIONS IN SCHEMA ext TO $EHRBASE_USER; +EOSQL \ No newline at end of file diff --git a/dockerfiles/scripts/test-temporal-tables.sh b/dockerfiles/scripts/test-temporal-tables.sh new file mode 100644 index 0000000..5190910 --- /dev/null +++ b/dockerfiles/scripts/test-temporal-tables.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +cd /scripts/temporal_tables + +# Build from source +make installcheck \ No newline at end of file