From caabec606700339e197fc1ff7165e7669d472d2e Mon Sep 17 00:00:00 2001 From: "Petr \"Stone\" Hracek" Date: Wed, 22 Feb 2023 12:16:42 +0100 Subject: [PATCH 1/5] Add the latest container-common-scripts Signed-off-by: Petr "Stone" Hracek --- common | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common b/common index 4d21ab6c..c1f46d90 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit 4d21ab6c92f5845aaa0c52f30abe4a86ac56c09c +Subproject commit c1f46d905f42267cbf0c0f6994c0f8e018bec3f8 From 1147b864893b438aa43050851c7d246b20ac858d Mon Sep 17 00:00:00 2001 From: "Petr \"Stone\" Hracek" Date: Wed, 22 Feb 2023 12:16:58 +0100 Subject: [PATCH 2/5] Add support for postgresql 14 for Fedora Signed-off-by: Petr "Stone" Hracek --- Makefile | 2 +- specs/multispec.yml | 19 +++++++++++++++++++ src/Dockerfile.fedora | 2 +- 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 71b7f998..eba393f5 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ # Variables are documented in common/build.sh. BASE_IMAGE_NAME = postgresql -VERSIONS = 10 12 13 15 +VERSIONS = 10 12 13 14 15 OPENSHIFT_NAMESPACES = 9.2 NOT_RELEASED_VERSIONS = diff --git a/specs/multispec.yml b/specs/multispec.yml index 97e82ef2..a62c9c91 100644 --- a/specs/multispec.yml +++ b/specs/multispec.yml @@ -136,6 +136,17 @@ specs: c9s_image_name: "sclorg/postgresql-{{ spec.short }}-c9s" latest_fedora: "f35" + "14": + version: "14" + prev_version: "13" + short: "14" + prev_short: "13" + common_image_name: "{{ spec.org }}/postgresql-{{ spec.short }}-{{ spec.prod }}" + rhel_image_name: "rhscl/postgresql-{{ spec.short }}-rhel7" + centos_image_name: "centos7/postgresql-{{ spec.short }}-centos7" + c9s_image_name: "sclorg/postgresql-{{ spec.short }}-c9s" + latest_fedora: "f37" + "15": version: "15" prev_version: "13" @@ -157,6 +168,14 @@ matrix: - rhel-9-x86_64 - centos-stream-9-x86_64 version: "12" + - distros: + - centos-7-x86_64 + - rhel-7-x86_64 + - centos-stream-8-x86_64 + - rhel-8-x86_64 + - centos-stream-9-x86_64 + - rhel-9-x86_64 + version: "14" - distros: - rhel-7-x86_64 - centos-7-x86_64 diff --git a/src/Dockerfile.fedora b/src/Dockerfile.fedora index 1503425c..f279329c 100644 --- a/src/Dockerfile.fedora +++ b/src/Dockerfile.fedora @@ -1,4 +1,4 @@ -{% if spec.version == "15" %} +{% if spec.version == "14" or spec.version == "15" %} FROM quay.io/fedora/s2i-core:37 {% else %} FROM quay.io/fedora/s2i-core:35 From 5c26b72038e72a16f45f507336692fa9fe34397c Mon Sep 17 00:00:00 2001 From: "Petr \"Stone\" Hracek" Date: Wed, 22 Feb 2023 12:21:12 +0100 Subject: [PATCH 3/5] Add support for pushing PostgreSQL 14 to Fedora quay.io registry Signed-off-by: Petr "Stone" Hracek --- .github/workflows/build-and-push.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/build-and-push.yml b/.github/workflows/build-and-push.yml index d1b6d987..e5775731 100644 --- a/.github/workflows/build-and-push.yml +++ b/.github/workflows/build-and-push.yml @@ -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" From 1e890371639a1b52f9ca5b94e78bae3d13e6f600 Mon Sep 17 00:00:00 2001 From: "Petr \"Stone\" Hracek" Date: Wed, 22 Feb 2023 12:36:58 +0100 Subject: [PATCH 4/5] Add dist-gen generated content for version 14 Signed-off-by: Petr "Stone" Hracek --- 14/Dockerfile.fedora | 84 +++ 14/README.md | 1 + 14/root/usr/bin/container-entrypoint | 3 + 14/root/usr/bin/run-postgresql | 58 +++ 14/root/usr/bin/run-postgresql-master | 5 + 14/root/usr/bin/run-postgresql-slave | 39 ++ 14/root/usr/bin/usage | 4 + 14/root/usr/libexec/check-container | 27 + 14/root/usr/libexec/fix-permissions | 39 ++ .../container-scripts/postgresql/README.md | 295 +++++++++++ .../container-scripts/postgresql/common.sh | 481 ++++++++++++++++++ ...ustom-postgresql-replication.conf.template | 7 + .../openshift-custom-postgresql.conf.template | 21 + .../openshift-custom-recovery.conf.template | 8 + .../container-scripts/postgresql/scl_enable | 3 + .../postgresql/start/set_passwords.sh | 23 + 14/s2i/bin/assemble | 14 + 14/s2i/bin/run | 1 + 14/s2i/bin/usage | 1 + 14/test | 1 + 20 files changed, 1115 insertions(+) create mode 100644 14/Dockerfile.fedora create mode 120000 14/README.md create mode 100755 14/root/usr/bin/container-entrypoint create mode 100755 14/root/usr/bin/run-postgresql create mode 100755 14/root/usr/bin/run-postgresql-master create mode 100755 14/root/usr/bin/run-postgresql-slave create mode 100755 14/root/usr/bin/usage create mode 100755 14/root/usr/libexec/check-container create mode 100755 14/root/usr/libexec/fix-permissions create mode 100644 14/root/usr/share/container-scripts/postgresql/README.md create mode 100644 14/root/usr/share/container-scripts/postgresql/common.sh create mode 100644 14/root/usr/share/container-scripts/postgresql/openshift-custom-postgresql-replication.conf.template create mode 100644 14/root/usr/share/container-scripts/postgresql/openshift-custom-postgresql.conf.template create mode 100644 14/root/usr/share/container-scripts/postgresql/openshift-custom-recovery.conf.template create mode 100644 14/root/usr/share/container-scripts/postgresql/scl_enable create mode 100644 14/root/usr/share/container-scripts/postgresql/start/set_passwords.sh create mode 100755 14/s2i/bin/assemble create mode 120000 14/s2i/bin/run create mode 100755 14/s2i/bin/usage create mode 120000 14/test diff --git a/14/Dockerfile.fedora b/14/Dockerfile.fedora new file mode 100644 index 00000000..586b11bf --- /dev/null +++ b/14/Dockerfile.fedora @@ -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 " \ + 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"] diff --git a/14/README.md b/14/README.md new file mode 120000 index 00000000..d359f030 --- /dev/null +++ b/14/README.md @@ -0,0 +1 @@ +root/usr/share/container-scripts/postgresql/README.md \ No newline at end of file diff --git a/14/root/usr/bin/container-entrypoint b/14/root/usr/bin/container-entrypoint new file mode 100755 index 00000000..5fc44481 --- /dev/null +++ b/14/root/usr/bin/container-entrypoint @@ -0,0 +1,3 @@ +#!/bin/bash + +exec "$@" diff --git a/14/root/usr/bin/run-postgresql b/14/root/usr/bin/run-postgresql new file mode 100755 index 00000000..2367e57e --- /dev/null +++ b/14/root/usr/bin/run-postgresql @@ -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 "$@" diff --git a/14/root/usr/bin/run-postgresql-master b/14/root/usr/bin/run-postgresql-master new file mode 100755 index 00000000..79e7cc24 --- /dev/null +++ b/14/root/usr/bin/run-postgresql-master @@ -0,0 +1,5 @@ +#!/bin/bash + +export ENABLE_REPLICATION=true + +exec run-postgresql "$@" diff --git a/14/root/usr/bin/run-postgresql-slave b/14/root/usr/bin/run-postgresql-slave new file mode 100755 index 00000000..586bf5d7 --- /dev/null +++ b/14/root/usr/bin/run-postgresql-slave @@ -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" <&2 <&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 diff --git a/14/root/usr/share/container-scripts/postgresql/README.md b/14/root/usr/share/container-scripts/postgresql/README.md new file mode 100644 index 00000000..0d33bee4 --- /dev/null +++ b/14/root/usr/share/container-scripts/postgresql/README.md @@ -0,0 +1,295 @@ +PostgreSQL 14 SQL Database Server container image +=============================================== + +This container image includes PostgreSQL 14 SQL database server for OpenShift and general usage. +Users can choose between RHEL, CentOS and Fedora based images. +The RHEL images are available in the [Red Hat Container Catalog](https://access.redhat.com/containers/), +the CentOS images are available on [Quay.io](https://quay.io/organization/centos7), +and the Fedora images are available in [Quay.io](https://quay.io/organization/fedora). +The resulting image can be run using [podman](https://github.com/containers/libpod). + +Note: while the examples in this README are calling `podman`, you can replace any such calls by `docker` with the same arguments + + +Description +----------- + +This container image provides a containerized packaging of the PostgreSQL postgres daemon +and client application. The postgres server daemon accepts connections from clients +and provides access to content from PostgreSQL databases on behalf of the clients. +You can find more information on the PostgreSQL project from the project Web site +(https://www.postgresql.org/). + + +Usage +----- + +For this, we will assume that you are using the `rhscl/postgresql-14-rhel7` image, available via `postgresql:14` imagestream tag in Openshift. +If you want to set only the mandatory environment variables and not store the database +in a host directory, execute the following command: + +``` +$ podman run -d --name postgresql_database -e POSTGRESQL_USER=user -e POSTGRESQL_PASSWORD=pass -e POSTGRESQL_DATABASE=db -p 5432:5432 rhscl/postgresql-14-rhel7 +``` + +This will create a container named `postgresql_database` running PostgreSQL with +database `db` and user with credentials `user:pass`. +> Note: user `postgres` is reserved for internal usage + +Port 5432 will be exposed +and mapped to the host. If you want your database to be persistent across container +executions, also add a `-v /host/db/path:/var/lib/pgsql/data` argument (see +below). This will be the PostgreSQL database cluster directory. + +The same can be achieved in an Openshift instance using templates provided by Openshift or available in [examples](https://github.com/sclorg/postgresql-container/tree/master/examples): + +``` +$ oc process -f examples/postgresql-ephemeral-template.json -p POSTGRESQL_VERSION=14 -p POSTGRESQL_USER=user -p POSTGRESQL_PASSWORD=pass -p POSTGRESQL_DATABASE=db | oc create -f - +``` + +If the database cluster directory is not initialized, the entrypoint script will +first run [`initdb`](http://www.postgresql.org/docs/14/static/app-initdb.html) +and setup necessary database users and passwords. After the database is initialized, +or if it was already present, [`postgres`](http://www.postgresql.org/docs/14/static/app-postgres.html) +is executed and will run as PID 1. You can stop the detached container by running +`podman stop postgresql_database`. + + + +Environment variables and volumes +--------------------------------- + +The image recognizes the following environment variables that you can set during +initialization by passing `-e VAR=VALUE` to the Docker run command. + +**`POSTGRESQL_USER`** + User name for PostgreSQL account to be created + +**`POSTGRESQL_PASSWORD`** + Password for the user account + +**`POSTGRESQL_DATABASE`** + Database name + +**`POSTGRESQL_ADMIN_PASSWORD`** + Password for the `postgres` admin account (optional) + + +Alternatively, the following options are related to migration scenario: + +**`POSTGRESQL_MIGRATION_REMOTE_HOST`** + Hostname/IP to migrate from + +**`POSTGRESQL_MIGRATION_ADMIN_PASSWORD`** + Password for the remote 'postgres' admin user + +**`POSTGRESQL_MIGRATION_IGNORE_ERRORS (optional, default 'no')`** + Set to 'yes' to ignore sql import errors + + +The following environment variables influence the PostgreSQL configuration file. They are all optional. + +**`POSTGRESQL_MAX_CONNECTIONS (default: 100)`** + The maximum number of client connections allowed + +**`POSTGRESQL_MAX_PREPARED_TRANSACTIONS (default: 0)`** + Sets the maximum number of transactions that can be in the "prepared" state. If you are using prepared transactions, you will probably want this to be at least as large as max_connections + +**`POSTGRESQL_SHARED_BUFFERS (default: 1/4 of memory limit or 32M)`** + Sets how much memory is dedicated to PostgreSQL to use for caching data + +**`POSTGRESQL_EFFECTIVE_CACHE_SIZE (default: 1/2 of memory limit or 128M)`** + Set to an estimate of how much memory is available for disk caching by the operating system and within the database itself + + +You can also set the following mount points by passing the `-v /host/dir:/container/dir:Z` flag to Docker. + +**`/var/lib/pgsql/data`** + PostgreSQL database cluster directory + + +**Notice: When mouting a directory from the host into the container, ensure that the mounted +directory has the appropriate permissions and that the owner and group of the directory +matches the user UID or name which is running inside the container.** + +Typically (unless you use `podman run -u` option) processes in container +run under UID 26, so -- on GNU/Linux -- you can fix the datadir permissions +for example by: + +``` +$ setfacl -m u:26:-wx /your/data/dir +$ podman run <...> -v /your/data/dir:/var/lib/pgsql/data:Z <...> +``` + + +Data migration +-------------- + +PostgreSQL container supports migration of data from remote PostgreSQL server. +You can run it like: + +``` +$ podman run -d --name postgresql_database \ + -e POSTGRESQL_MIGRATION_REMOTE_HOST=172.17.0.2 \ + -e POSTGRESQL_MIGRATION_ADMIN_PASSWORD=remoteAdminP@ssword \ + [ OPTIONAL_CONFIGURATION_VARIABLES ] + rhel8/postgresql-13 +``` + +The migration is done the **dump and restore** way (running `pg_dumpall` against +remote cluster and importing the dump locally by `psql`). Because the process +is streamed (unix pipeline), there are no intermediate dump files created during +this process to not waste additional storage space. + +If some SQL commands fail during applying, the default behavior +of the migration script is to fail as well to ensure the **all** or **nothing** +result of scripted, unattended migration. In most common cases, successful +migration is expected (but not guaranteed!), given you migrate from +a previous version of PostgreSQL server container, that is created using +the same principles as this one (e.g. migration from +`rhel8/postgresql-12` to `rhel8/postgresql-13`). +Migration from a different kind of PostgreSQL container can likely fail. + +If this **all** or **nothing** principle is inadequate for you, and you know +what you are doing, there's optional `POSTGRESQL_MIGRATION_IGNORE_ERRORS` option +which does **best effort** migration (some data might be lost, it is up to user +to review the standard error output and fix the issues manually in +post-migration time). + +Please keep in mind that the container image provides help for users' +convenience, but fully automatic migration is not guaranteed. Thus, before you +start proceeding with the database migration, get prepared to perform manual +steps in order to get all your data migrated. + +Note that you might not use variables like `POSTGRESQL_USER` in migration +scenario, all the data (including info about databases, roles or passwords are +copied from old cluster). Ensure that you use the same +`OPTIONAL_CONFIGURATION_VARIABLES` as you used for initialization of the old +PostgreSQL container. If some non-default configuration is done on remote +cluster, you might need to copy the configuration files manually, too. + +Security warning: Note that the IP communication between old and new PostgreSQL +clusters is not encrypted by default, it is up to user to configure SSL on +remote cluster or ensure security via different means. + +PostgreSQL auto-tuning +---------------------- + +When the PostgreSQL image is run with the `--memory` parameter set and if there +are no values provided for `POSTGRESQL_SHARED_BUFFERS` and +`POSTGRESQL_EFFECTIVE_CACHE_SIZE` those values are automatically calculated +based on the value provided in the `--memory` parameter. + +The values are calculated based on the +[upstream](https://wiki.postgresql.org/wiki/Tuning_Your_PostgreSQL_Server) +formulas. For the `shared_buffers` we use 1/4 of given memory and for the +`effective_cache_size` we set the value to 1/2 of the given memory. + +PostgreSQL admin account +------------------------ +The admin account `postgres` has no password set by default, only allowing local +connections. You can set it by setting the `POSTGRESQL_ADMIN_PASSWORD` environment +variable when initializing your container. This will allow you to login to the +`postgres` account remotely. Local connections will still not require a password. + + +Changing passwords +------------------ + +Since passwords are part of the image configuration, the only supported method +to change passwords for the database user (`POSTGRESQL_USER`) and `postgres` +admin user is by changing the environment variables `POSTGRESQL_PASSWORD` and +`POSTGRESQL_ADMIN_PASSWORD`, respectively. + +Changing database passwords through SQL statements or any way other than through +the environment variables aforementioned will cause a mismatch between the +values stored in the variables and the actual passwords. Whenever a database +container starts it will reset the passwords to the values stored in the +environment variables. + + + + +Extending image +---------------- + +This image can be extended in Openshift using the `Source` build strategy or via the standalone +[source-to-image](https://github.com/openshift/source-to-image) application (where available). +For this, we will assume that you are using the `rhscl/postgresql-14-rhel7` image, +available via `postgresql:14` imagestream tag in Openshift. + +For example to build customized image `new-postgresql` +with configuration from `https://github.com/sclorg/postgresql-container/tree/master/examples/extending-image` run: + +``` +$ oc new-app postgresql:14~https://github.com/sclorg/postgresql-container.git \ + --name new-postgresql \ + --context-dir examples/extending-image/ \ + -e POSTGRESQL_USER=user \ + -e POSTGRESQL_DATABASE=db \ + -e POSTGRESQL_PASSWORD=password +``` + +or via `s2i`: + +``` +$ s2i build --context-dir examples/extending-image/ https://github.com/sclorg/postgresql-container.git rhscl/postgresql-14-rhel7 new-postgresql +``` + +The directory passed to Openshift should contain one or more of the +following directories: + + +##### `postgresql-pre-start/` + +Source all `*.sh` files from this directory during early start of the +container. There's no PostgreSQL daemon running on background. + + +##### `postgresql-cfg/` + +Contained configuration files (`*.conf`) will be included at the end of image +postgresql.conf file. + + +##### `postgresql-init/` + +Contained shell scripts (`*.sh`) are sourced when the database is freshly +initialized (after successful initdb run which made the data directory +non-empty). At the time of sourcing these scripts, the local PostgreSQL +server is running. For re-deployments scenarios with persistent data +directory, the scripts are not sourced (no-op). + + +##### `postgresql-start/` + +Same sematics as `postgresql-init/`, except that these scripts are +always sourced (after `postgresql-init/` scripts, if they exist). + + +---------------------------------------------- + +During the s2i build all provided files are copied into `/opt/app-root/src` +directory in the new image. Only one +file with the same name can be used for customization and user provided files +are preferred over default files in `/usr/share/container-scripts/`- +so it is possible to overwrite them. + + +Troubleshooting +--------------- +At first the postgres daemon writes its logs to the standard output, so these are available in the container log. The log can be examined by running: + + podman logs + +Then log output is redirected to logging collector process and will appear in directory "pg_log". + + +See also +-------- +Dockerfile and other sources for this container image are available on +https://github.com/sclorg/postgresql-container. +In that repository, the Dockerfile for CentOS is called Dockerfile, the Dockerfile +for RHEL7 is called Dockerfile.rhel7, the Dockerfile for RHEL8 is called Dockerfile.rhel8, +the Dockerfile for RHEL9 is called Dockerfile.rhel9, +and the Dockerfile for Fedora is called Dockerfile.fedora. diff --git a/14/root/usr/share/container-scripts/postgresql/common.sh b/14/root/usr/share/container-scripts/postgresql/common.sh new file mode 100644 index 00000000..a99ee557 --- /dev/null +++ b/14/root/usr/share/container-scripts/postgresql/common.sh @@ -0,0 +1,481 @@ +# Configuration settings. +export POSTGRESQL_MAX_CONNECTIONS=${POSTGRESQL_MAX_CONNECTIONS:-100} +export POSTGRESQL_MAX_PREPARED_TRANSACTIONS=${POSTGRESQL_MAX_PREPARED_TRANSACTIONS:-0} + +# Perform auto-tuning based on the container cgroups limits (only when the +# limits are set). +# Users can still override this by setting the POSTGRESQL_SHARED_BUFFERS +# and POSTGRESQL_EFFECTIVE_CACHE_SIZE variables. +if [[ "${NO_MEMORY_LIMIT:-}" == "true" || -z "${MEMORY_LIMIT_IN_BYTES:-}" ]]; then + export POSTGRESQL_SHARED_BUFFERS=${POSTGRESQL_SHARED_BUFFERS:-32MB} + export POSTGRESQL_EFFECTIVE_CACHE_SIZE=${POSTGRESQL_EFFECTIVE_CACHE_SIZE:-128MB} +else + # Use 1/4 of given memory for shared buffers + shared_buffers_computed="$(($MEMORY_LIMIT_IN_BYTES/1024/1024/4))MB" + # Setting effective_cache_size to 1/2 of total memory would be a normal conservative setting, + effective_cache="$(($MEMORY_LIMIT_IN_BYTES/1024/1024/2))MB" + export POSTGRESQL_SHARED_BUFFERS=${POSTGRESQL_SHARED_BUFFERS:-$shared_buffers_computed} + export POSTGRESQL_EFFECTIVE_CACHE_SIZE=${POSTGRESQL_EFFECTIVE_CACHE_SIZE:-$effective_cache} +fi + +export POSTGRESQL_RECOVERY_FILE=$HOME/openshift-custom-recovery.conf +export POSTGRESQL_CONFIG_FILE=$HOME/openshift-custom-postgresql.conf + +postinitdb_actions= + +# match . files when moving userdata below +shopt -s dotglob +# extglob enables the !(userdata) glob pattern below. +shopt -s extglob + +function usage() { + if [ $# == 1 ]; then + echo >&2 "error: $1" + fi + + cat >&2 </dev/null) + # FIXME: This is for debugging (docker run) + if [ -v POSTGRESQL_MASTER_IP ]; then + endpoints=${POSTGRESQL_MASTER_IP:-} + fi + if [ -z "$endpoints" ]; then + >&2 echo "Failed to resolve PostgreSQL master IP address" + exit 3 + fi + echo -n "$(echo $endpoints | cut -d ' ' -f 1)" +} + +# Converts the version in format x.y or x.y.z to a number. +version2number () +{ + local old_IFS=$IFS + local to_print= depth=${2-3} width=${3-2} sum=0 one_part + IFS='.' + set -- $1 + while test $depth -ge 1; do + depth=$(( depth - 1 )) + part=${1-0} ; shift || : + printf "%0${width}d" "$part" + done + IFS=$old_IFS +} + +# On non-intel arches, data_sync_retry = off does not work +# Upstream discussion: https://www.postgresql.org/message-id/CA+mCpegfOUph2U4ZADtQT16dfbkjjYNJL1bSTWErsazaFjQW9A@mail.gmail.com +# Upstream changes that caused this issue: +# https://github.com/postgres/postgres/commit/483520eca426fb1b428e8416d1d014ac5ad80ef4 +# https://github.com/postgres/postgres/commit/9ccdd7f66e3324d2b6d3dec282cfa9ff084083f1 +# RHBZ: https://bugzilla.redhat.com/show_bug.cgi?id=1779150 +# Special handle of data_sync_retry should handle only in some cases. +# These cases are: non-intel architectures, and version higher or equal 12.0, 10.7, 9.6.12 +# Return value 0 means the hack is needed. +function should_hack_data_sync_retry() { + [ "$(uname -p)" == 'x86_64' ] && return 1 + local version_number=$(version2number "$(pg_ctl -V | sed -e 's/^pg_ctl (PostgreSQL) //')") + # this matches all 12.x and versions of 10.x where we need the hack + [ "$version_number" -ge 100700 ] && return 0 + # this matches all 10.x that were not matched above + [ "$version_number" -ge 100000 ] && return 1 + # this matches all 9.x where need the hack + [ "$version_number" -ge 090612 ] && return 0 + # all rest should be older 9.x releases + return 1 +} + +# New config is generated every time a container is created. It only contains +# additional custom settings and is included from $PGDATA/postgresql.conf. +function generate_postgresql_config() { + envsubst \ + < "${CONTAINER_SCRIPTS_PATH}/openshift-custom-postgresql.conf.template" \ + > "${POSTGRESQL_CONFIG_FILE}" + + if [ "${ENABLE_REPLICATION}" == "true" ]; then + envsubst \ + < "${CONTAINER_SCRIPTS_PATH}/openshift-custom-postgresql-replication.conf.template" \ + >> "${POSTGRESQL_CONFIG_FILE}" + fi + + if should_hack_data_sync_retry ; then + echo "data_sync_retry = on" >>"${POSTGRESQL_CONFIG_FILE}" + fi + + ( + shopt -s nullglob + for conf in "${APP_DATA}"/src/postgresql-cfg/*.conf; do + echo include \'${conf}\' >> "${POSTGRESQL_CONFIG_FILE}" + done + ) +} + +function generate_postgresql_recovery_config() { + envsubst \ + < "${CONTAINER_SCRIPTS_PATH}/openshift-custom-recovery.conf.template" \ + > "${POSTGRESQL_RECOVERY_FILE}" +} + +# Generate passwd file based on current uid +function generate_passwd_file() { + export USER_ID=$(id -u) + export GROUP_ID=$(id -g) + grep -v -e ^postgres -e ^$USER_ID /etc/passwd > "$HOME/passwd" + echo "postgres:x:${USER_ID}:${GROUP_ID}:PostgreSQL Server:${HOME}:/bin/bash" >> "$HOME/passwd" + export LD_PRELOAD=libnss_wrapper.so + export NSS_WRAPPER_PASSWD=${HOME}/passwd + export NSS_WRAPPER_GROUP=/etc/group +} + +initdb_wrapper () +{ + # Initialize the database cluster with utf8 support enabled by default. + # This might affect performance, see: + # http://www.postgresql.org/docs/14/static/locale.html + LANG=${LANG:-en_US.utf8} "$@" +} + +function initialize_database() { + initdb_wrapper initdb + + # PostgreSQL configuration. + cat >> "$PGDATA/postgresql.conf" <> "$PGDATA/pg_hba.conf" <&2 "\n========== \$PGDATA upgrade: %s -> %s ==========\n\n" \ + "$POSTGRESQL_PREV_VERSION" \ + "$POSTGRESQL_VERSION" + + info_msg () { printf >&2 "\n===> $*\n\n" ;} + + # pg_upgrade writes logs to cwd, so go to the persistent storage first + cd "$HOME"/data + + # disable this because of scl_source, 'set +u' just makes the code ugly + # anyways + set +u + + # we need to have the old SCL enabled, otherwise the $old_pgengine is not + # working. The scl_source script doesn't pay attention to non-zero exit + # statuses, so use 'set +e'. + set +e + source scl_source enable $old_collection + set -e + + case $POSTGRESQL_UPGRADE in + copy) # we accept this + ;; + hardlink) + optimized=: + ;; + *) + echo >&2 "Unsupported value: \$POSTGRESQL_UPGRADE=$POSTGRESQL_UPGRADE" + false + ;; + esac + + # Ensure $PGDATA_new doesn't exist yet, so we can immediately remove it if + # there's some problem. + test ! -e "$PGDATA_new" + + # initialize the database + info_msg "Initialize new data directory; we will migrate to that." + initdb_cmd=( initdb_wrapper "$new_pgengine"/initdb "$PGDATA_new" ) + eval "\${initdb_cmd[@]} ${POSTGRESQL_UPGRADE_INITDB_OPTIONS-}" || \ + { rm -rf "$PGDATA_new" ; false ; } + + upgrade_cmd=( + "$new_pgengine"/pg_upgrade + "--old-bindir=$old_pgengine" + "--new-bindir=$new_pgengine" + "--old-datadir=$PGDATA" + "--new-datadir=$PGDATA_new" + ) + + # Dangerous --link option, we loose $DATADIR if something goes wrong. + ! $optimized || upgrade_cmd+=(--link) + + # User-specififed options for pg_upgrade. + eval "upgrade_cmd+=(${POSTGRESQL_UPGRADE_PGUPGRADE_OPTIONS-})" + + # On non-intel arches the data_sync_retry set to on + sed -i -e 's/data_sync_retry/#data_sync_retry/' "${POSTGRESQL_CONFIG_FILE}" + + # the upgrade + info_msg "Starting the pg_upgrade process." + + # Once we stop support for PostgreSQL 9.4, we don't need + # REDHAT_PGUPGRADE_FROM_RHEL hack as we don't upgrade from 9.2 -- that means + # that we don't need to fiddle with unix_socket_director{y,ies} option. + REDHAT_PGUPGRADE_FROM_RHEL=1 \ + "${upgrade_cmd[@]}" || { cat $(find "$PGDATA_new"/.. -name pg_upgrade_server.log) ; rm -rf "$PGDATA_new" && false ; } + + # Move the important configuration and remove old data. This is highly + # careless, but we can't do more for this over-automatized process. + info_msg "Swap the old and new PGDATA and cleanup." + mv "$PGDATA"/*.conf "$PGDATA_new" + rm -rf "$PGDATA" + mv "$PGDATA_new" "$PGDATA" + + # Get back the option we changed above + sed -i -e 's/#data_sync_retry/data_sync_retry/' "${POSTGRESQL_CONFIG_FILE}" + + info_msg "Upgrade DONE." +) + + +# Run right after container startup, when the data volume is already initialized +# (not initialized by this container run) and thus there exists a chance that +# the data was generated by incompatible PostgreSQL major version. +try_pgupgrade () +{ + local versionfile="$PGDATA"/PG_VERSION version upgrade_available + + # This file always exists. + test -f "$versionfile" + version=$(cat "$versionfile") + + # If we don't support pg_upgrade, skip. + test -z "${POSTGRESQL_PREV_VERSION-}" && return 0 + + if test "$POSTGRESQL_VERSION" = "$version"; then + # No need to call pg_upgrade. + + # Mistakenly requests upgrade? If not, just start the DB. + test -z "${POSTGRESQL_UPGRADE-}" && return 0 + + # Make _sure_ we have this safety-belt here, otherwise our users would + # just specify '-e POSTGRESQL_UPGRADE=hardlink' permanently, even for + # re-deployment cases when upgrade is not needed. Setting such + # unfortunate default could mean that pg_upgrade might (after some user + # mistake) migrate (or even destruct, especially with --link) the old data + # directory with limited rollback options, if any. + echo >&2 + echo >&2 "== WARNING!! ==" + echo >&2 "PostgreSQL server version matches the datadir PG_VERSION." + echo >&2 "The \$POSTGRESQL_UPGRADE makes no sense and you probably" + echo >&2 "made some mistake, keeping the variable set you might" + echo >&2 "risk a data loss in future!" + echo >&2 "===============" + echo >&2 + + # Exit here, but allow _really explicit_ foot-shot. + ${POSTGRESQL_UPGRADE_FORCE-false} + return 0 + fi + + # At this point in code we know that PG_VERSION doesn't match the PostgreSQL + # server major version; this might mean that user either (a) mistakenly + # deploys from a bad image, or (b) user wants to perform upgrade. For the + # upgrade we require explicit request -- just to avoid disasters in (a)-cases. + + if test -z "${POSTGRESQL_UPGRADE-}"; then + echo >&2 "Incompatible data directory. This container image provides" + echo >&2 "PostgreSQL '$POSTGRESQL_VERSION', but data directory is of" + echo >&2 "version '$version'." + echo >&2 + echo >&2 "This image supports automatic data directory upgrade from" + echo >&2 "'$POSTGRESQL_PREV_VERSION', please _carefully_ consult image documentation" + echo >&2 "about how to use the '\$POSTGRESQL_UPGRADE' startup option." + # We could wait for postgresql startup failure (there's no risk of data dir + # corruption), but fail rather early. + false + fi + + # We support pg_upgrade process only from previous version of this container + # (upgrade to N to N+1 is possible, so e.g. 9.4 to 9.5). + if test "$POSTGRESQL_PREV_VERSION" != "$version"; then + echo >&2 "With this container image you can only upgrade from data directory" + echo >&2 "of version '$POSTGRESQL_PREV_VERSION', not '$version'." + false + fi + + run_pgupgrade +} + +# get_matched_files PATTERN DIR [DIR ...] +# --------------------------------------- +# Print all basenames for files matching PATTERN in DIRs. +get_matched_files () +{ + local pattern=$1 dir + shift + for dir; do + test -d "$dir" || continue + find -L "$dir" -maxdepth 1 -type f -name "$pattern" -printf "%f\n" + done +} + +# process_extending_files DIR [DIR ...] +# ------------------------------------- +# Source all *.sh files in DIRs in alphabetical order, but if the file exists in +# more then one DIR, source only the first occurrence (first found wins). +process_extending_files() +{ + local filename dir + while read filename ; do + for dir in "$@"; do + local file="$dir/$filename" + if test -f "$file"; then + echo "=> sourcing $file ..." + source "$file" + set -e # ensure that users don't mistakenly change this + break + fi + done + done <<<"$(get_matched_files '*.sh' "$@" | sort -u)" +} diff --git a/14/root/usr/share/container-scripts/postgresql/openshift-custom-postgresql-replication.conf.template b/14/root/usr/share/container-scripts/postgresql/openshift-custom-postgresql-replication.conf.template new file mode 100644 index 00000000..d133e511 --- /dev/null +++ b/14/root/usr/share/container-scripts/postgresql/openshift-custom-postgresql-replication.conf.template @@ -0,0 +1,7 @@ +# required on master for replication +wal_level = hot_standby # minimal, archive, hot_standby, or logical +max_wal_senders = 6 # max number of walsender processes +wal_keep_size = 6400 # number of segments (400) * size of segments (16MB each); 0 disables + +# required on replicas for replication +hot_standby = on diff --git a/14/root/usr/share/container-scripts/postgresql/openshift-custom-postgresql.conf.template b/14/root/usr/share/container-scripts/postgresql/openshift-custom-postgresql.conf.template new file mode 100644 index 00000000..3c2bc7f3 --- /dev/null +++ b/14/root/usr/share/container-scripts/postgresql/openshift-custom-postgresql.conf.template @@ -0,0 +1,21 @@ +# +# Custom OpenShift configuration. +# +# NOTE: This file is rewritten every time the container is started! +# Changes to this file will be overwritten. +# + +# Listen on all interfaces. +listen_addresses = '*' + +# Determines the maximum number of concurrent connections to the database server. Default: 100 +max_connections = ${POSTGRESQL_MAX_CONNECTIONS} + +# Allow each connection to use a prepared transaction +max_prepared_transactions = ${POSTGRESQL_MAX_PREPARED_TRANSACTIONS} + +# Sets the amount of memory the database server uses for shared memory buffers. Default: 32MB +shared_buffers = ${POSTGRESQL_SHARED_BUFFERS} + +# Sets the planner's assumption about the effective size of the disk cache that is available to a single query +effective_cache_size = ${POSTGRESQL_EFFECTIVE_CACHE_SIZE} diff --git a/14/root/usr/share/container-scripts/postgresql/openshift-custom-recovery.conf.template b/14/root/usr/share/container-scripts/postgresql/openshift-custom-recovery.conf.template new file mode 100644 index 00000000..58d8e336 --- /dev/null +++ b/14/root/usr/share/container-scripts/postgresql/openshift-custom-recovery.conf.template @@ -0,0 +1,8 @@ +# +# Custom OpenShift configuration. +# +# NOTE: This file is rewritten every time the container is started! +# Changes to this file will be overwritten. +# + +primary_conninfo = 'host=${MASTER_FQDN} port=5432 user=${POSTGRESQL_MASTER_USER} password=${POSTGRESQL_MASTER_PASSWORD}' diff --git a/14/root/usr/share/container-scripts/postgresql/scl_enable b/14/root/usr/share/container-scripts/postgresql/scl_enable new file mode 100644 index 00000000..1d967f9b --- /dev/null +++ b/14/root/usr/share/container-scripts/postgresql/scl_enable @@ -0,0 +1,3 @@ +# This will make scl collection binaries work out of box. +unset BASH_ENV PROMPT_COMMAND ENV +source scl_source enable $ENABLED_COLLECTIONS diff --git a/14/root/usr/share/container-scripts/postgresql/start/set_passwords.sh b/14/root/usr/share/container-scripts/postgresql/start/set_passwords.sh new file mode 100644 index 00000000..60d70e36 --- /dev/null +++ b/14/root/usr/share/container-scripts/postgresql/start/set_passwords.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +_psql () { psql --set ON_ERROR_STOP=1 "$@" ; } + +if [[ ",$postinitdb_actions," = *,simple_db,* ]]; then +_psql --set=username="$POSTGRESQL_USER" \ + --set=password="$POSTGRESQL_PASSWORD" \ +<<< "ALTER USER :\"username\" WITH ENCRYPTED PASSWORD :'password';" +fi + +if [ -v POSTGRESQL_MASTER_USER ]; then +_psql --set=masteruser="$POSTGRESQL_MASTER_USER" \ + --set=masterpass="$POSTGRESQL_MASTER_PASSWORD" \ +<<'EOF' +ALTER USER :"masteruser" WITH REPLICATION; +ALTER USER :"masteruser" WITH ENCRYPTED PASSWORD :'masterpass'; +EOF +fi + +if [ -v POSTGRESQL_ADMIN_PASSWORD ]; then +_psql --set=adminpass="$POSTGRESQL_ADMIN_PASSWORD" \ +<<<"ALTER USER \"postgres\" WITH ENCRYPTED PASSWORD :'adminpass';" +fi diff --git a/14/s2i/bin/assemble b/14/s2i/bin/assemble new file mode 100755 index 00000000..6ed8f7aa --- /dev/null +++ b/14/s2i/bin/assemble @@ -0,0 +1,14 @@ +#!/bin/bash + +set -o errexit +set -o nounset +set -o pipefail + +shopt -s dotglob +echo "---> Installing application source ..." + + +mv /tmp/src/* ./ + +# Fix source directory permissions +/usr/libexec/fix-permissions --read-only ./ diff --git a/14/s2i/bin/run b/14/s2i/bin/run new file mode 120000 index 00000000..a7f4076b --- /dev/null +++ b/14/s2i/bin/run @@ -0,0 +1 @@ +/usr/bin/run-postgresql \ No newline at end of file diff --git a/14/s2i/bin/usage b/14/s2i/bin/usage new file mode 100755 index 00000000..9f413123 --- /dev/null +++ b/14/s2i/bin/usage @@ -0,0 +1 @@ +groff -t -man -ETascii /help.1 diff --git a/14/test b/14/test new file mode 120000 index 00000000..419df4f9 --- /dev/null +++ b/14/test @@ -0,0 +1 @@ +../test \ No newline at end of file From a7e01e7fc4381101177263319034a6135ae51140 Mon Sep 17 00:00:00 2001 From: "Petr \"Stone\" Hracek" Date: Wed, 22 Feb 2023 12:38:12 +0100 Subject: [PATCH 5/5] Update main README.md file Signed-off-by: Petr "Stone" Hracek --- 14/root/usr/share/container-scripts/postgresql/common.sh | 2 +- README.md | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/14/root/usr/share/container-scripts/postgresql/common.sh b/14/root/usr/share/container-scripts/postgresql/common.sh index a99ee557..7261e532 100644 --- a/14/root/usr/share/container-scripts/postgresql/common.sh +++ b/14/root/usr/share/container-scripts/postgresql/common.sh @@ -130,7 +130,7 @@ version2number () # These cases are: non-intel architectures, and version higher or equal 12.0, 10.7, 9.6.12 # Return value 0 means the hack is needed. function should_hack_data_sync_retry() { - [ "$(uname -p)" == 'x86_64' ] && return 1 + [ "$(uname -m)" == 'x86_64' ] && return 1 local version_number=$(version2number "$(pg_ctl -V | sed -e 's/^pg_ctl (PostgreSQL) //')") # this matches all 12.x and versions of 10.x where we need the hack [ "$version_number" -ge 100700 ] && return 0 diff --git a/README.md b/README.md index c59e1ffc..e7dc0b27 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ Images available on Quay are: * Fedora [postgresql-11](https://quay.io/repository/fedora/postgresql-11) * Fedora [postgresql-12](https://quay.io/repository/fedora/postgresql-12) * Fedora [postgresql-13](https://quay.io/repository/fedora/postgresql-13) +* Fedora [postgresql-14](https://quay.io/repository/fedora/postgresql-14) * Fedora [postgresql-15](https://quay.io/repository/fedora/postgresql-15) This repository contains Dockerfiles for PostgreSQL images for OpenShift. @@ -35,6 +36,7 @@ PostgreSQL versions currently supported are: * [postgresql-10](https://github.com/sclorg/postgresql-container/tree/master/10) * [postgresql-12](https://github.com/sclorg/postgresql-container/tree/master/12) * [postgresql-13](https://github.com/sclorg/postgresql-container/tree/master/13) +* [postgresql-14](https://github.com/sclorg/postgresql-container/tree/master/14) * [postgresql-15](https://github.com/sclorg/postgresql-container/tree/master/15) RHEL versions currently supported are: @@ -107,6 +109,9 @@ see [usage documentation](https://github.com/sclorg/postgresql-container/tree/ma For information about usage of Dockerfile for PostgreSQL 13, see [usage documentation](https://github.com/sclorg/postgresql-container/tree/master/13). +For information about usage of Dockerfile for PostgreSQL 14, +see [usage documentation](https://github.com/sclorg/postgresql-container/tree/master/14). + For information about usage of Dockerfile for PostgreSQL 15, see [usage documentation](https://github.com/sclorg/postgresql-container/tree/master/15).