Skip to content

Support PostgreSQL 14 on Fedora #497

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/workflows/build-and-push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,13 @@ jobs:
quayio_token: "QUAY_IMAGE_FEDORA_BUILDER_TOKEN"
image_name: "postgresql-13"
docker_context: 13
- dockerfile: "14/Dockerfile.fedora"
registry_namespace: "fedora"
tag: "14"
quayio_username: "QUAY_IMAGE_FEDORA_BUILDER_USERNAME"
quayio_token: "QUAY_IMAGE_FEDORA_BUILDER_TOKEN"
image_name: "postgresql-14"
docker_context: 14
- dockerfile: "15/Dockerfile.fedora"
registry_namespace: "fedora"
tag: "15"
Expand Down
84 changes: 84 additions & 0 deletions 14/Dockerfile.fedora
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
FROM quay.io/fedora/s2i-core:37

# PostgreSQL image for OpenShift.
# Volumes:
# * /var/lib/psql/data - Database cluster for PostgreSQL
# Environment:
# * $POSTGRESQL_USER - Database user name
# * $POSTGRESQL_PASSWORD - User's password
# * $POSTGRESQL_DATABASE - Name of the database to create
# * $POSTGRESQL_ADMIN_PASSWORD (Optional) - Password for the 'postgres'
# PostgreSQL administrative account

ENV NAME=postgresql \
VERSION=0 \
ARCH=x86_64 \
\
POSTGRESQL_VERSION=14 \
POSTGRESQL_PREV_VERSION=13 \
HOME=/var/lib/pgsql \
PGUSER=postgres \
APP_DATA=/opt/app-root

ENV SUMMARY="PostgreSQL is an advanced Object-Relational database management system" \
DESCRIPTION="PostgreSQL is an advanced Object-Relational database management system (DBMS). \
The image contains the client and server programs that you'll need to \
create, run, maintain and access a PostgreSQL DBMS server."

LABEL summary="$SUMMARY" \
description="$DESCRIPTION" \
io.k8s.description="$DESCRIPTION" \
io.k8s.display-name="PostgreSQL 14" \
io.openshift.expose-services="5432:postgresql" \
io.openshift.tags="database,postgresql,postgresql14" \
com.redhat.component="$NAME" \
maintainer="SoftwareCollections.org <[email protected]>" \
name="fedora/$NAME-14" \
version="0" \
usage="docker run -d --name postgresql_database -e POSTGRESQL_USER=user -e POSTGRESQL_PASSWORD=pass -e POSTGRESQL_DATABASE=db -p 5432:5432 quay.io/fedora/$NAME-14"

EXPOSE 5432

COPY root/usr/libexec/fix-permissions /usr/libexec/fix-permissions

# This image must forever use UID 26 for postgres user so our volumes are
# safe in the future. This should *never* change, the last test is there
# to make sure of that.
RUN INSTALL_PKGS="rsync tar gettext bind-utils postgresql-server postgresql-contrib nss_wrapper " && \
INSTALL_PKGS+="findutils xz" && \
INSTALL_PKGS+=" pgaudit" && \
dnf -y module enable postgresql:14 && \
dnf -y --setopt=tsflags=nodocs install $INSTALL_PKGS && \
rpm -V $INSTALL_PKGS && \
postgres -V | grep -qe "$POSTGRESQL_VERSION\." && echo "Found VERSION $POSTGRESQL_VERSION" && \
dnf clean all && \
test "$(id postgres)" = "uid=26(postgres) gid=26(postgres) groups=26(postgres)" && \
mkdir -p /var/lib/pgsql/data && \
/usr/libexec/fix-permissions /var/lib/pgsql /var/run/postgresql

# Get prefix path and path to scripts rather than hard-code them in scripts
ENV CONTAINER_SCRIPTS_PATH=/usr/share/container-scripts/postgresql

COPY root /
COPY ./s2i/bin/ $STI_SCRIPTS_PATH

VOLUME ["/var/lib/pgsql/data"]

# S2I permission fixes
# --------------------
# 1. unless specified otherwise (or - equivalently - we are in OpenShift), s2i
# build process would be executed as 'uid=26(postgres) gid=26(postgres)'.
# Such process wouldn't be able to execute the default 'assemble' script
# correctly (it transitively executes 'fix-permissions' script). So let's
# add the 'postgres' user into 'root' group here
#
# 2. we call fix-permissions on $APP_DATA here directly (UID=0 during build
# anyways) to assure that s2i process is actually able to _read_ the
# user-specified scripting.
RUN usermod -a -G root postgres && \
/usr/libexec/fix-permissions --read-only "$APP_DATA"

USER 26

ENTRYPOINT ["container-entrypoint"]
CMD ["run-postgresql"]
1 change: 1 addition & 0 deletions 14/README.md
3 changes: 3 additions & 0 deletions 14/root/usr/bin/container-entrypoint
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/bash

exec "$@"
58 changes: 58 additions & 0 deletions 14/root/usr/bin/run-postgresql
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#!/bin/bash

export ENABLE_REPLICATION=${ENABLE_REPLICATION:-false}

set -eu
export_vars=$(cgroup-limits) ; export $export_vars

source "${CONTAINER_SCRIPTS_PATH}/common.sh"

set_pgdata

process_extending_files \
"${APP_DATA}/src/postgresql-pre-start" \
"${CONTAINER_SCRIPTS_PATH}/pre-start"

check_env_vars
generate_passwd_file
generate_postgresql_config

# Is this brand new data volume?
PG_INITIALIZED=false

if [ ! -f "$PGDATA/postgresql.conf" ]; then
initialize_database
PG_INITIALIZED=:
else
try_pgupgrade
fi

# Use insanely large timeout (24h) to ensure that the potential recovery has
# enough time here to happen (unless liveness probe kills us). Note that in
# case of server failure this command still exists immediately.
pg_ctl start -w --timeout 86400 -o "-h ''"

# This is just a pedantic safety measure (the timeout above is unlikely to
# happen), but `pt_ctl -w` is not reliable prior to PostgreSQL v10 where it
# returns exit_status=0 even if the server is still starting. For more info
# see the issue#297 and
# https://www.postgresql.org/message-id/CAB7nPqSJs85wK9aknm%3D_jmS6GnH3SQBhpzKcqs8Qo2LhEg2etw%40mail.gmail.com
pg_isready

if $PG_INITIALIZED ; then
process_extending_files \
"${APP_DATA}/src/postgresql-init" \
"${CONTAINER_SCRIPTS_PATH}/init"
migrate_db
create_users
fi

process_extending_files \
"${APP_DATA}/src/postgresql-start" \
"${CONTAINER_SCRIPTS_PATH}/start"

pg_ctl stop

unset_env_vars
echo "Starting server..."
exec postgres "$@"
5 changes: 5 additions & 0 deletions 14/root/usr/bin/run-postgresql-master
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/bash

export ENABLE_REPLICATION=true

exec run-postgresql "$@"
39 changes: 39 additions & 0 deletions 14/root/usr/bin/run-postgresql-slave
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/bin/bash

export ENABLE_REPLICATION=true

set -eu
export_vars=$(cgroup-limits) ; export $export_vars

source "$CONTAINER_SCRIPTS_PATH"/common.sh

set_pgdata

function initialize_replica() {
echo "Initializing PostgreSQL slave ..."
# TODO: Validate and reuse existing data?
rm -rf $PGDATA
PGPASSWORD="${POSTGRESQL_MASTER_PASSWORD}" pg_basebackup -X fetch --no-password --pgdata ${PGDATA} --host=${MASTER_FQDN} --port=5432 -U "${POSTGRESQL_MASTER_USER}"

# PostgreSQL recovery configuration.
generate_postgresql_recovery_config
cat >> "$PGDATA/postgresql.auto.conf" <<EOF

# Custom OpenShift recovery configuration:
include '${POSTGRESQL_RECOVERY_FILE}'
EOF
# activate standby mode
touch "$PGDATA/standby.signal"
}

check_env_vars
generate_passwd_file
generate_postgresql_config

wait_for_postgresql_master
export MASTER_FQDN=$(postgresql_master_addr)
initialize_replica

unset_env_vars
echo "Starting server..."
exec postgres "$@"
4 changes: 4 additions & 0 deletions 14/root/usr/bin/usage
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash

cat /usr/share/container-scripts/postgresql/README.md

27 changes: 27 additions & 0 deletions 14/root/usr/libexec/check-container
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#! /bin/sh

# Try whether the PostgreSQL in container accepts connections.
#
# With --live, be tolerant to starting PG server. If the /bin/postgres binary
# has not been executed yet (the shell script is initializing the container),
# wait for it (this script might run forever, we expect that the timeout is
# maintained externally).

test -z "$ENABLED_COLLECTIONS" || . scl_source enable $ENABLED_COLLECTIONS

if test x"$1" = "x--live"; then
# Since livenessProbe is about to detect container deadlocks, and we
# so far don't know about real deadlocks to be detected -- we keep
# liveness probe to report that container is always ready (as long as
# we are able to execute shell, enable collections, etc., which is
# good for container sanity testing anyways).
exit 0
fi

# Readiness check follows, the --timeout is set to "infinite" because it
# is handled externally (readinessProbe.timeoutSeconds).
pg_isready -q \
-h 127.0.0.1 \
${POSTGRESQL_USER+-U "$POSTGRESQL_USER"} \
${POSTGRESQL_DATABASE+-d "$POSTGRESQL_DATABASE"} \
--timeout 0
39 changes: 39 additions & 0 deletions 14/root/usr/libexec/fix-permissions
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/bin/sh

documentation="\
Recursively fix permissions on the given directories to allow GID=0
read/write regular files and read/write/execute directories.

To run this command, you have to be in the group root=0!"

uid=26
write=w

usage ()
{
cat >&2 <<EOF
$0: Error: ${1-usage error}

Usage: $0 [--read-only] DIR [DIR ..]

$documentation
EOF
exit 1
}

while test $# -gt 0; do
case $1 in
--read-only) write= ; shift ;;
*) break ;;
esac
done

test $# -eq 0 && usage "no DIR specified"

for dir; do
test -d "$dir" || usage "no such directory '$dir'"
echo >&2 "fixing permissions on '$dir' directory"
find "$dir" -exec chown "$uid:0" {} \;
find "$dir" -exec chmod "g+r$write" {} \;
find "$dir" -type d -exec chmod g+x {} +
done
Loading