From c86568af4a6861cb30b8f1b736b0868a3129bdd6 Mon Sep 17 00:00:00 2001 From: Tianon Gravi Date: Wed, 29 Nov 2023 15:50:55 -0800 Subject: [PATCH] Add new "docker-ensure-initdb.sh" script This mimics the behavior of `docker-entrypoint.sh` before it starts the PostgreSQL server. It has three main goals/uses: 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution (no-op if database is already initialized) 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use (error if database is already initialized) --- .gitattributes | 7 +-- 12/alpine3.18/Dockerfile | 3 +- 12/alpine3.18/docker-ensure-initdb.sh | 71 +++++++++++++++++++++++++++ 12/alpine3.18/docker-entrypoint.sh | 1 + 12/alpine3.19/Dockerfile | 3 +- 12/alpine3.19/docker-ensure-initdb.sh | 71 +++++++++++++++++++++++++++ 12/alpine3.19/docker-entrypoint.sh | 1 + 12/bookworm/Dockerfile | 3 +- 12/bookworm/docker-ensure-initdb.sh | 71 +++++++++++++++++++++++++++ 12/bookworm/docker-entrypoint.sh | 1 + 12/bullseye/Dockerfile | 3 +- 12/bullseye/docker-ensure-initdb.sh | 71 +++++++++++++++++++++++++++ 12/bullseye/docker-entrypoint.sh | 1 + 13/alpine3.18/Dockerfile | 3 +- 13/alpine3.18/docker-ensure-initdb.sh | 71 +++++++++++++++++++++++++++ 13/alpine3.18/docker-entrypoint.sh | 1 + 13/alpine3.19/Dockerfile | 3 +- 13/alpine3.19/docker-ensure-initdb.sh | 71 +++++++++++++++++++++++++++ 13/alpine3.19/docker-entrypoint.sh | 1 + 13/bookworm/Dockerfile | 3 +- 13/bookworm/docker-ensure-initdb.sh | 71 +++++++++++++++++++++++++++ 13/bookworm/docker-entrypoint.sh | 1 + 13/bullseye/Dockerfile | 3 +- 13/bullseye/docker-ensure-initdb.sh | 71 +++++++++++++++++++++++++++ 13/bullseye/docker-entrypoint.sh | 1 + 14/alpine3.18/Dockerfile | 3 +- 14/alpine3.18/docker-ensure-initdb.sh | 71 +++++++++++++++++++++++++++ 14/alpine3.18/docker-entrypoint.sh | 1 + 14/alpine3.19/Dockerfile | 3 +- 14/alpine3.19/docker-ensure-initdb.sh | 71 +++++++++++++++++++++++++++ 14/alpine3.19/docker-entrypoint.sh | 1 + 14/bookworm/Dockerfile | 3 +- 14/bookworm/docker-ensure-initdb.sh | 71 +++++++++++++++++++++++++++ 14/bookworm/docker-entrypoint.sh | 1 + 14/bullseye/Dockerfile | 3 +- 14/bullseye/docker-ensure-initdb.sh | 71 +++++++++++++++++++++++++++ 14/bullseye/docker-entrypoint.sh | 1 + 15/alpine3.18/Dockerfile | 3 +- 15/alpine3.18/docker-ensure-initdb.sh | 71 +++++++++++++++++++++++++++ 15/alpine3.18/docker-entrypoint.sh | 1 + 15/alpine3.19/Dockerfile | 3 +- 15/alpine3.19/docker-ensure-initdb.sh | 71 +++++++++++++++++++++++++++ 15/alpine3.19/docker-entrypoint.sh | 1 + 15/bookworm/Dockerfile | 3 +- 15/bookworm/docker-ensure-initdb.sh | 71 +++++++++++++++++++++++++++ 15/bookworm/docker-entrypoint.sh | 1 + 15/bullseye/Dockerfile | 3 +- 15/bullseye/docker-ensure-initdb.sh | 71 +++++++++++++++++++++++++++ 15/bullseye/docker-entrypoint.sh | 1 + 16/alpine3.18/Dockerfile | 3 +- 16/alpine3.18/docker-ensure-initdb.sh | 71 +++++++++++++++++++++++++++ 16/alpine3.18/docker-entrypoint.sh | 1 + 16/alpine3.19/Dockerfile | 3 +- 16/alpine3.19/docker-ensure-initdb.sh | 71 +++++++++++++++++++++++++++ 16/alpine3.19/docker-entrypoint.sh | 1 + 16/bookworm/Dockerfile | 3 +- 16/bookworm/docker-ensure-initdb.sh | 71 +++++++++++++++++++++++++++ 16/bookworm/docker-entrypoint.sh | 1 + 16/bullseye/Dockerfile | 3 +- 16/bullseye/docker-ensure-initdb.sh | 71 +++++++++++++++++++++++++++ 16/bullseye/docker-entrypoint.sh | 1 + Dockerfile-alpine.template | 3 +- Dockerfile-debian.template | 3 +- apply-templates.sh | 4 +- docker-ensure-initdb.sh | 71 +++++++++++++++++++++++++++ docker-entrypoint.sh | 1 + 66 files changed, 1562 insertions(+), 27 deletions(-) create mode 100755 12/alpine3.18/docker-ensure-initdb.sh create mode 100755 12/alpine3.19/docker-ensure-initdb.sh create mode 100755 12/bookworm/docker-ensure-initdb.sh create mode 100755 12/bullseye/docker-ensure-initdb.sh create mode 100755 13/alpine3.18/docker-ensure-initdb.sh create mode 100755 13/alpine3.19/docker-ensure-initdb.sh create mode 100755 13/bookworm/docker-ensure-initdb.sh create mode 100755 13/bullseye/docker-ensure-initdb.sh create mode 100755 14/alpine3.18/docker-ensure-initdb.sh create mode 100755 14/alpine3.19/docker-ensure-initdb.sh create mode 100755 14/bookworm/docker-ensure-initdb.sh create mode 100755 14/bullseye/docker-ensure-initdb.sh create mode 100755 15/alpine3.18/docker-ensure-initdb.sh create mode 100755 15/alpine3.19/docker-ensure-initdb.sh create mode 100755 15/bookworm/docker-ensure-initdb.sh create mode 100755 15/bullseye/docker-ensure-initdb.sh create mode 100755 16/alpine3.18/docker-ensure-initdb.sh create mode 100755 16/alpine3.19/docker-ensure-initdb.sh create mode 100755 16/bookworm/docker-ensure-initdb.sh create mode 100755 16/bullseye/docker-ensure-initdb.sh create mode 100755 docker-ensure-initdb.sh diff --git a/.gitattributes b/.gitattributes index 14a112269e..4d1ee06a43 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,4 @@ -/*/**/Dockerfile linguist-generated -/*/**/docker-entrypoint.sh linguist-generated -/Dockerfile*.template linguist-language=Dockerfile +/*/**/Dockerfile linguist-generated +/*/**/docker-ensure-initdb.sh linguist-generated +/*/**/docker-entrypoint.sh linguist-generated +/Dockerfile*.template linguist-language=Dockerfile diff --git a/12/alpine3.18/Dockerfile b/12/alpine3.18/Dockerfile index fde4049703..3e001b1aa2 100644 --- a/12/alpine3.18/Dockerfile +++ b/12/alpine3.18/Dockerfile @@ -169,7 +169,8 @@ ENV PGDATA /var/lib/postgresql/data RUN mkdir -p "$PGDATA" && chown -R postgres:postgres "$PGDATA" && chmod 1777 "$PGDATA" VOLUME /var/lib/postgresql/data -COPY docker-entrypoint.sh /usr/local/bin/ +COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ +RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh ENTRYPOINT ["docker-entrypoint.sh"] # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL diff --git a/12/alpine3.18/docker-ensure-initdb.sh b/12/alpine3.18/docker-ensure-initdb.sh new file mode 100755 index 0000000000..2a9758656e --- /dev/null +++ b/12/alpine3.18/docker-ensure-initdb.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +# +# This script is intended for three main use cases: +# +# 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior +# +# 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution +# (no-op if database is already initialized) +# +# 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use +# (error if database is already initialized) +# + +source /usr/local/bin/docker-entrypoint.sh + +# arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) +if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then + set -- postgres "$@" +fi + +# see also "_main" in "docker-entrypoint.sh" + +docker_setup_env +# setup data directories and permissions (when run as root) +docker_create_db_directories +if [ "$(id -u)" = '0' ]; then + # then restart script as postgres user + exec su-exec postgres "$BASH_SOURCE" "$@" +fi + +# only run initialization on an empty data directory +if [ -z "$DATABASE_ALREADY_EXISTS" ]; then + docker_verify_minimum_env + + # check dir permissions to reduce likelihood of half-initialized database + ls /docker-entrypoint-initdb.d/ > /dev/null + + docker_init_database_dir + pg_setup_hba_conf "$@" + + # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless + # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS + export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" + docker_temp_server_start "$@" + + docker_setup_db + docker_process_init_files /docker-entrypoint-initdb.d/* + + docker_temp_server_stop + unset PGPASSWORD +else + self="$(basename "$0")" + case "$self" in + docker-ensure-initdb.sh) + echo >&2 "$self: note: database already initialized in '$PGDATA'!" + exit 0 + ;; + + docker-enforce-initdb.sh) + echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" + exit 1 + ;; + + *) + echo >&2 "$self: error: unknown file name: $self" + exit 99 + ;; + esac +fi diff --git a/12/alpine3.18/docker-entrypoint.sh b/12/alpine3.18/docker-entrypoint.sh index a383a36487..151d75ef96 100755 --- a/12/alpine3.18/docker-entrypoint.sh +++ b/12/alpine3.18/docker-entrypoint.sh @@ -225,6 +225,7 @@ docker_setup_env() { : "${POSTGRES_HOST_AUTH_METHOD:=}" declare -g DATABASE_ALREADY_EXISTS + : "${DATABASE_ALREADY_EXISTS:=}" # look specifically for PG_VERSION, as it is expected in the DB dir if [ -s "$PGDATA/PG_VERSION" ]; then DATABASE_ALREADY_EXISTS='true' diff --git a/12/alpine3.19/Dockerfile b/12/alpine3.19/Dockerfile index 6f3347c0ff..05b1be0566 100644 --- a/12/alpine3.19/Dockerfile +++ b/12/alpine3.19/Dockerfile @@ -169,7 +169,8 @@ ENV PGDATA /var/lib/postgresql/data RUN mkdir -p "$PGDATA" && chown -R postgres:postgres "$PGDATA" && chmod 1777 "$PGDATA" VOLUME /var/lib/postgresql/data -COPY docker-entrypoint.sh /usr/local/bin/ +COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ +RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh ENTRYPOINT ["docker-entrypoint.sh"] # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL diff --git a/12/alpine3.19/docker-ensure-initdb.sh b/12/alpine3.19/docker-ensure-initdb.sh new file mode 100755 index 0000000000..2a9758656e --- /dev/null +++ b/12/alpine3.19/docker-ensure-initdb.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +# +# This script is intended for three main use cases: +# +# 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior +# +# 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution +# (no-op if database is already initialized) +# +# 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use +# (error if database is already initialized) +# + +source /usr/local/bin/docker-entrypoint.sh + +# arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) +if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then + set -- postgres "$@" +fi + +# see also "_main" in "docker-entrypoint.sh" + +docker_setup_env +# setup data directories and permissions (when run as root) +docker_create_db_directories +if [ "$(id -u)" = '0' ]; then + # then restart script as postgres user + exec su-exec postgres "$BASH_SOURCE" "$@" +fi + +# only run initialization on an empty data directory +if [ -z "$DATABASE_ALREADY_EXISTS" ]; then + docker_verify_minimum_env + + # check dir permissions to reduce likelihood of half-initialized database + ls /docker-entrypoint-initdb.d/ > /dev/null + + docker_init_database_dir + pg_setup_hba_conf "$@" + + # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless + # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS + export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" + docker_temp_server_start "$@" + + docker_setup_db + docker_process_init_files /docker-entrypoint-initdb.d/* + + docker_temp_server_stop + unset PGPASSWORD +else + self="$(basename "$0")" + case "$self" in + docker-ensure-initdb.sh) + echo >&2 "$self: note: database already initialized in '$PGDATA'!" + exit 0 + ;; + + docker-enforce-initdb.sh) + echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" + exit 1 + ;; + + *) + echo >&2 "$self: error: unknown file name: $self" + exit 99 + ;; + esac +fi diff --git a/12/alpine3.19/docker-entrypoint.sh b/12/alpine3.19/docker-entrypoint.sh index a383a36487..151d75ef96 100755 --- a/12/alpine3.19/docker-entrypoint.sh +++ b/12/alpine3.19/docker-entrypoint.sh @@ -225,6 +225,7 @@ docker_setup_env() { : "${POSTGRES_HOST_AUTH_METHOD:=}" declare -g DATABASE_ALREADY_EXISTS + : "${DATABASE_ALREADY_EXISTS:=}" # look specifically for PG_VERSION, as it is expected in the DB dir if [ -s "$PGDATA/PG_VERSION" ]; then DATABASE_ALREADY_EXISTS='true' diff --git a/12/bookworm/Dockerfile b/12/bookworm/Dockerfile index 165a9666bf..647dc8dc43 100644 --- a/12/bookworm/Dockerfile +++ b/12/bookworm/Dockerfile @@ -184,7 +184,8 @@ ENV PGDATA /var/lib/postgresql/data RUN mkdir -p "$PGDATA" && chown -R postgres:postgres "$PGDATA" && chmod 1777 "$PGDATA" VOLUME /var/lib/postgresql/data -COPY docker-entrypoint.sh /usr/local/bin/ +COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ +RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh ENTRYPOINT ["docker-entrypoint.sh"] # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL diff --git a/12/bookworm/docker-ensure-initdb.sh b/12/bookworm/docker-ensure-initdb.sh new file mode 100755 index 0000000000..ae1f6b6b90 --- /dev/null +++ b/12/bookworm/docker-ensure-initdb.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +# +# This script is intended for three main use cases: +# +# 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior +# +# 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution +# (no-op if database is already initialized) +# +# 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use +# (error if database is already initialized) +# + +source /usr/local/bin/docker-entrypoint.sh + +# arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) +if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then + set -- postgres "$@" +fi + +# see also "_main" in "docker-entrypoint.sh" + +docker_setup_env +# setup data directories and permissions (when run as root) +docker_create_db_directories +if [ "$(id -u)" = '0' ]; then + # then restart script as postgres user + exec gosu postgres "$BASH_SOURCE" "$@" +fi + +# only run initialization on an empty data directory +if [ -z "$DATABASE_ALREADY_EXISTS" ]; then + docker_verify_minimum_env + + # check dir permissions to reduce likelihood of half-initialized database + ls /docker-entrypoint-initdb.d/ > /dev/null + + docker_init_database_dir + pg_setup_hba_conf "$@" + + # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless + # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS + export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" + docker_temp_server_start "$@" + + docker_setup_db + docker_process_init_files /docker-entrypoint-initdb.d/* + + docker_temp_server_stop + unset PGPASSWORD +else + self="$(basename "$0")" + case "$self" in + docker-ensure-initdb.sh) + echo >&2 "$self: note: database already initialized in '$PGDATA'!" + exit 0 + ;; + + docker-enforce-initdb.sh) + echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" + exit 1 + ;; + + *) + echo >&2 "$self: error: unknown file name: $self" + exit 99 + ;; + esac +fi diff --git a/12/bookworm/docker-entrypoint.sh b/12/bookworm/docker-entrypoint.sh index 0ae0ecf8c2..6d197bc01f 100755 --- a/12/bookworm/docker-entrypoint.sh +++ b/12/bookworm/docker-entrypoint.sh @@ -225,6 +225,7 @@ docker_setup_env() { : "${POSTGRES_HOST_AUTH_METHOD:=}" declare -g DATABASE_ALREADY_EXISTS + : "${DATABASE_ALREADY_EXISTS:=}" # look specifically for PG_VERSION, as it is expected in the DB dir if [ -s "$PGDATA/PG_VERSION" ]; then DATABASE_ALREADY_EXISTS='true' diff --git a/12/bullseye/Dockerfile b/12/bullseye/Dockerfile index 6a6dd9ee59..82386336a2 100644 --- a/12/bullseye/Dockerfile +++ b/12/bullseye/Dockerfile @@ -184,7 +184,8 @@ ENV PGDATA /var/lib/postgresql/data RUN mkdir -p "$PGDATA" && chown -R postgres:postgres "$PGDATA" && chmod 1777 "$PGDATA" VOLUME /var/lib/postgresql/data -COPY docker-entrypoint.sh /usr/local/bin/ +COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ +RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh ENTRYPOINT ["docker-entrypoint.sh"] # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL diff --git a/12/bullseye/docker-ensure-initdb.sh b/12/bullseye/docker-ensure-initdb.sh new file mode 100755 index 0000000000..ae1f6b6b90 --- /dev/null +++ b/12/bullseye/docker-ensure-initdb.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +# +# This script is intended for three main use cases: +# +# 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior +# +# 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution +# (no-op if database is already initialized) +# +# 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use +# (error if database is already initialized) +# + +source /usr/local/bin/docker-entrypoint.sh + +# arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) +if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then + set -- postgres "$@" +fi + +# see also "_main" in "docker-entrypoint.sh" + +docker_setup_env +# setup data directories and permissions (when run as root) +docker_create_db_directories +if [ "$(id -u)" = '0' ]; then + # then restart script as postgres user + exec gosu postgres "$BASH_SOURCE" "$@" +fi + +# only run initialization on an empty data directory +if [ -z "$DATABASE_ALREADY_EXISTS" ]; then + docker_verify_minimum_env + + # check dir permissions to reduce likelihood of half-initialized database + ls /docker-entrypoint-initdb.d/ > /dev/null + + docker_init_database_dir + pg_setup_hba_conf "$@" + + # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless + # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS + export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" + docker_temp_server_start "$@" + + docker_setup_db + docker_process_init_files /docker-entrypoint-initdb.d/* + + docker_temp_server_stop + unset PGPASSWORD +else + self="$(basename "$0")" + case "$self" in + docker-ensure-initdb.sh) + echo >&2 "$self: note: database already initialized in '$PGDATA'!" + exit 0 + ;; + + docker-enforce-initdb.sh) + echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" + exit 1 + ;; + + *) + echo >&2 "$self: error: unknown file name: $self" + exit 99 + ;; + esac +fi diff --git a/12/bullseye/docker-entrypoint.sh b/12/bullseye/docker-entrypoint.sh index 0ae0ecf8c2..6d197bc01f 100755 --- a/12/bullseye/docker-entrypoint.sh +++ b/12/bullseye/docker-entrypoint.sh @@ -225,6 +225,7 @@ docker_setup_env() { : "${POSTGRES_HOST_AUTH_METHOD:=}" declare -g DATABASE_ALREADY_EXISTS + : "${DATABASE_ALREADY_EXISTS:=}" # look specifically for PG_VERSION, as it is expected in the DB dir if [ -s "$PGDATA/PG_VERSION" ]; then DATABASE_ALREADY_EXISTS='true' diff --git a/13/alpine3.18/Dockerfile b/13/alpine3.18/Dockerfile index cd9936c4c4..22fbdc8ed4 100644 --- a/13/alpine3.18/Dockerfile +++ b/13/alpine3.18/Dockerfile @@ -169,7 +169,8 @@ ENV PGDATA /var/lib/postgresql/data RUN mkdir -p "$PGDATA" && chown -R postgres:postgres "$PGDATA" && chmod 1777 "$PGDATA" VOLUME /var/lib/postgresql/data -COPY docker-entrypoint.sh /usr/local/bin/ +COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ +RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh ENTRYPOINT ["docker-entrypoint.sh"] # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL diff --git a/13/alpine3.18/docker-ensure-initdb.sh b/13/alpine3.18/docker-ensure-initdb.sh new file mode 100755 index 0000000000..2a9758656e --- /dev/null +++ b/13/alpine3.18/docker-ensure-initdb.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +# +# This script is intended for three main use cases: +# +# 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior +# +# 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution +# (no-op if database is already initialized) +# +# 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use +# (error if database is already initialized) +# + +source /usr/local/bin/docker-entrypoint.sh + +# arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) +if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then + set -- postgres "$@" +fi + +# see also "_main" in "docker-entrypoint.sh" + +docker_setup_env +# setup data directories and permissions (when run as root) +docker_create_db_directories +if [ "$(id -u)" = '0' ]; then + # then restart script as postgres user + exec su-exec postgres "$BASH_SOURCE" "$@" +fi + +# only run initialization on an empty data directory +if [ -z "$DATABASE_ALREADY_EXISTS" ]; then + docker_verify_minimum_env + + # check dir permissions to reduce likelihood of half-initialized database + ls /docker-entrypoint-initdb.d/ > /dev/null + + docker_init_database_dir + pg_setup_hba_conf "$@" + + # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless + # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS + export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" + docker_temp_server_start "$@" + + docker_setup_db + docker_process_init_files /docker-entrypoint-initdb.d/* + + docker_temp_server_stop + unset PGPASSWORD +else + self="$(basename "$0")" + case "$self" in + docker-ensure-initdb.sh) + echo >&2 "$self: note: database already initialized in '$PGDATA'!" + exit 0 + ;; + + docker-enforce-initdb.sh) + echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" + exit 1 + ;; + + *) + echo >&2 "$self: error: unknown file name: $self" + exit 99 + ;; + esac +fi diff --git a/13/alpine3.18/docker-entrypoint.sh b/13/alpine3.18/docker-entrypoint.sh index a383a36487..151d75ef96 100755 --- a/13/alpine3.18/docker-entrypoint.sh +++ b/13/alpine3.18/docker-entrypoint.sh @@ -225,6 +225,7 @@ docker_setup_env() { : "${POSTGRES_HOST_AUTH_METHOD:=}" declare -g DATABASE_ALREADY_EXISTS + : "${DATABASE_ALREADY_EXISTS:=}" # look specifically for PG_VERSION, as it is expected in the DB dir if [ -s "$PGDATA/PG_VERSION" ]; then DATABASE_ALREADY_EXISTS='true' diff --git a/13/alpine3.19/Dockerfile b/13/alpine3.19/Dockerfile index e82d1b9db4..2bc16e1885 100644 --- a/13/alpine3.19/Dockerfile +++ b/13/alpine3.19/Dockerfile @@ -169,7 +169,8 @@ ENV PGDATA /var/lib/postgresql/data RUN mkdir -p "$PGDATA" && chown -R postgres:postgres "$PGDATA" && chmod 1777 "$PGDATA" VOLUME /var/lib/postgresql/data -COPY docker-entrypoint.sh /usr/local/bin/ +COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ +RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh ENTRYPOINT ["docker-entrypoint.sh"] # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL diff --git a/13/alpine3.19/docker-ensure-initdb.sh b/13/alpine3.19/docker-ensure-initdb.sh new file mode 100755 index 0000000000..2a9758656e --- /dev/null +++ b/13/alpine3.19/docker-ensure-initdb.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +# +# This script is intended for three main use cases: +# +# 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior +# +# 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution +# (no-op if database is already initialized) +# +# 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use +# (error if database is already initialized) +# + +source /usr/local/bin/docker-entrypoint.sh + +# arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) +if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then + set -- postgres "$@" +fi + +# see also "_main" in "docker-entrypoint.sh" + +docker_setup_env +# setup data directories and permissions (when run as root) +docker_create_db_directories +if [ "$(id -u)" = '0' ]; then + # then restart script as postgres user + exec su-exec postgres "$BASH_SOURCE" "$@" +fi + +# only run initialization on an empty data directory +if [ -z "$DATABASE_ALREADY_EXISTS" ]; then + docker_verify_minimum_env + + # check dir permissions to reduce likelihood of half-initialized database + ls /docker-entrypoint-initdb.d/ > /dev/null + + docker_init_database_dir + pg_setup_hba_conf "$@" + + # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless + # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS + export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" + docker_temp_server_start "$@" + + docker_setup_db + docker_process_init_files /docker-entrypoint-initdb.d/* + + docker_temp_server_stop + unset PGPASSWORD +else + self="$(basename "$0")" + case "$self" in + docker-ensure-initdb.sh) + echo >&2 "$self: note: database already initialized in '$PGDATA'!" + exit 0 + ;; + + docker-enforce-initdb.sh) + echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" + exit 1 + ;; + + *) + echo >&2 "$self: error: unknown file name: $self" + exit 99 + ;; + esac +fi diff --git a/13/alpine3.19/docker-entrypoint.sh b/13/alpine3.19/docker-entrypoint.sh index a383a36487..151d75ef96 100755 --- a/13/alpine3.19/docker-entrypoint.sh +++ b/13/alpine3.19/docker-entrypoint.sh @@ -225,6 +225,7 @@ docker_setup_env() { : "${POSTGRES_HOST_AUTH_METHOD:=}" declare -g DATABASE_ALREADY_EXISTS + : "${DATABASE_ALREADY_EXISTS:=}" # look specifically for PG_VERSION, as it is expected in the DB dir if [ -s "$PGDATA/PG_VERSION" ]; then DATABASE_ALREADY_EXISTS='true' diff --git a/13/bookworm/Dockerfile b/13/bookworm/Dockerfile index d97ed4221c..1086785f54 100644 --- a/13/bookworm/Dockerfile +++ b/13/bookworm/Dockerfile @@ -186,7 +186,8 @@ ENV PGDATA /var/lib/postgresql/data RUN mkdir -p "$PGDATA" && chown -R postgres:postgres "$PGDATA" && chmod 1777 "$PGDATA" VOLUME /var/lib/postgresql/data -COPY docker-entrypoint.sh /usr/local/bin/ +COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ +RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh ENTRYPOINT ["docker-entrypoint.sh"] # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL diff --git a/13/bookworm/docker-ensure-initdb.sh b/13/bookworm/docker-ensure-initdb.sh new file mode 100755 index 0000000000..ae1f6b6b90 --- /dev/null +++ b/13/bookworm/docker-ensure-initdb.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +# +# This script is intended for three main use cases: +# +# 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior +# +# 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution +# (no-op if database is already initialized) +# +# 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use +# (error if database is already initialized) +# + +source /usr/local/bin/docker-entrypoint.sh + +# arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) +if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then + set -- postgres "$@" +fi + +# see also "_main" in "docker-entrypoint.sh" + +docker_setup_env +# setup data directories and permissions (when run as root) +docker_create_db_directories +if [ "$(id -u)" = '0' ]; then + # then restart script as postgres user + exec gosu postgres "$BASH_SOURCE" "$@" +fi + +# only run initialization on an empty data directory +if [ -z "$DATABASE_ALREADY_EXISTS" ]; then + docker_verify_minimum_env + + # check dir permissions to reduce likelihood of half-initialized database + ls /docker-entrypoint-initdb.d/ > /dev/null + + docker_init_database_dir + pg_setup_hba_conf "$@" + + # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless + # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS + export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" + docker_temp_server_start "$@" + + docker_setup_db + docker_process_init_files /docker-entrypoint-initdb.d/* + + docker_temp_server_stop + unset PGPASSWORD +else + self="$(basename "$0")" + case "$self" in + docker-ensure-initdb.sh) + echo >&2 "$self: note: database already initialized in '$PGDATA'!" + exit 0 + ;; + + docker-enforce-initdb.sh) + echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" + exit 1 + ;; + + *) + echo >&2 "$self: error: unknown file name: $self" + exit 99 + ;; + esac +fi diff --git a/13/bookworm/docker-entrypoint.sh b/13/bookworm/docker-entrypoint.sh index 0ae0ecf8c2..6d197bc01f 100755 --- a/13/bookworm/docker-entrypoint.sh +++ b/13/bookworm/docker-entrypoint.sh @@ -225,6 +225,7 @@ docker_setup_env() { : "${POSTGRES_HOST_AUTH_METHOD:=}" declare -g DATABASE_ALREADY_EXISTS + : "${DATABASE_ALREADY_EXISTS:=}" # look specifically for PG_VERSION, as it is expected in the DB dir if [ -s "$PGDATA/PG_VERSION" ]; then DATABASE_ALREADY_EXISTS='true' diff --git a/13/bullseye/Dockerfile b/13/bullseye/Dockerfile index d88766fc44..0f2b30c55e 100644 --- a/13/bullseye/Dockerfile +++ b/13/bullseye/Dockerfile @@ -186,7 +186,8 @@ ENV PGDATA /var/lib/postgresql/data RUN mkdir -p "$PGDATA" && chown -R postgres:postgres "$PGDATA" && chmod 1777 "$PGDATA" VOLUME /var/lib/postgresql/data -COPY docker-entrypoint.sh /usr/local/bin/ +COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ +RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh ENTRYPOINT ["docker-entrypoint.sh"] # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL diff --git a/13/bullseye/docker-ensure-initdb.sh b/13/bullseye/docker-ensure-initdb.sh new file mode 100755 index 0000000000..ae1f6b6b90 --- /dev/null +++ b/13/bullseye/docker-ensure-initdb.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +# +# This script is intended for three main use cases: +# +# 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior +# +# 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution +# (no-op if database is already initialized) +# +# 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use +# (error if database is already initialized) +# + +source /usr/local/bin/docker-entrypoint.sh + +# arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) +if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then + set -- postgres "$@" +fi + +# see also "_main" in "docker-entrypoint.sh" + +docker_setup_env +# setup data directories and permissions (when run as root) +docker_create_db_directories +if [ "$(id -u)" = '0' ]; then + # then restart script as postgres user + exec gosu postgres "$BASH_SOURCE" "$@" +fi + +# only run initialization on an empty data directory +if [ -z "$DATABASE_ALREADY_EXISTS" ]; then + docker_verify_minimum_env + + # check dir permissions to reduce likelihood of half-initialized database + ls /docker-entrypoint-initdb.d/ > /dev/null + + docker_init_database_dir + pg_setup_hba_conf "$@" + + # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless + # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS + export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" + docker_temp_server_start "$@" + + docker_setup_db + docker_process_init_files /docker-entrypoint-initdb.d/* + + docker_temp_server_stop + unset PGPASSWORD +else + self="$(basename "$0")" + case "$self" in + docker-ensure-initdb.sh) + echo >&2 "$self: note: database already initialized in '$PGDATA'!" + exit 0 + ;; + + docker-enforce-initdb.sh) + echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" + exit 1 + ;; + + *) + echo >&2 "$self: error: unknown file name: $self" + exit 99 + ;; + esac +fi diff --git a/13/bullseye/docker-entrypoint.sh b/13/bullseye/docker-entrypoint.sh index 0ae0ecf8c2..6d197bc01f 100755 --- a/13/bullseye/docker-entrypoint.sh +++ b/13/bullseye/docker-entrypoint.sh @@ -225,6 +225,7 @@ docker_setup_env() { : "${POSTGRES_HOST_AUTH_METHOD:=}" declare -g DATABASE_ALREADY_EXISTS + : "${DATABASE_ALREADY_EXISTS:=}" # look specifically for PG_VERSION, as it is expected in the DB dir if [ -s "$PGDATA/PG_VERSION" ]; then DATABASE_ALREADY_EXISTS='true' diff --git a/14/alpine3.18/Dockerfile b/14/alpine3.18/Dockerfile index 9856dcc54b..341fb0e3f9 100644 --- a/14/alpine3.18/Dockerfile +++ b/14/alpine3.18/Dockerfile @@ -172,7 +172,8 @@ ENV PGDATA /var/lib/postgresql/data RUN mkdir -p "$PGDATA" && chown -R postgres:postgres "$PGDATA" && chmod 1777 "$PGDATA" VOLUME /var/lib/postgresql/data -COPY docker-entrypoint.sh /usr/local/bin/ +COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ +RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh ENTRYPOINT ["docker-entrypoint.sh"] # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL diff --git a/14/alpine3.18/docker-ensure-initdb.sh b/14/alpine3.18/docker-ensure-initdb.sh new file mode 100755 index 0000000000..2a9758656e --- /dev/null +++ b/14/alpine3.18/docker-ensure-initdb.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +# +# This script is intended for three main use cases: +# +# 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior +# +# 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution +# (no-op if database is already initialized) +# +# 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use +# (error if database is already initialized) +# + +source /usr/local/bin/docker-entrypoint.sh + +# arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) +if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then + set -- postgres "$@" +fi + +# see also "_main" in "docker-entrypoint.sh" + +docker_setup_env +# setup data directories and permissions (when run as root) +docker_create_db_directories +if [ "$(id -u)" = '0' ]; then + # then restart script as postgres user + exec su-exec postgres "$BASH_SOURCE" "$@" +fi + +# only run initialization on an empty data directory +if [ -z "$DATABASE_ALREADY_EXISTS" ]; then + docker_verify_minimum_env + + # check dir permissions to reduce likelihood of half-initialized database + ls /docker-entrypoint-initdb.d/ > /dev/null + + docker_init_database_dir + pg_setup_hba_conf "$@" + + # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless + # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS + export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" + docker_temp_server_start "$@" + + docker_setup_db + docker_process_init_files /docker-entrypoint-initdb.d/* + + docker_temp_server_stop + unset PGPASSWORD +else + self="$(basename "$0")" + case "$self" in + docker-ensure-initdb.sh) + echo >&2 "$self: note: database already initialized in '$PGDATA'!" + exit 0 + ;; + + docker-enforce-initdb.sh) + echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" + exit 1 + ;; + + *) + echo >&2 "$self: error: unknown file name: $self" + exit 99 + ;; + esac +fi diff --git a/14/alpine3.18/docker-entrypoint.sh b/14/alpine3.18/docker-entrypoint.sh index a383a36487..151d75ef96 100755 --- a/14/alpine3.18/docker-entrypoint.sh +++ b/14/alpine3.18/docker-entrypoint.sh @@ -225,6 +225,7 @@ docker_setup_env() { : "${POSTGRES_HOST_AUTH_METHOD:=}" declare -g DATABASE_ALREADY_EXISTS + : "${DATABASE_ALREADY_EXISTS:=}" # look specifically for PG_VERSION, as it is expected in the DB dir if [ -s "$PGDATA/PG_VERSION" ]; then DATABASE_ALREADY_EXISTS='true' diff --git a/14/alpine3.19/Dockerfile b/14/alpine3.19/Dockerfile index 20ac720b77..fdd06f4f20 100644 --- a/14/alpine3.19/Dockerfile +++ b/14/alpine3.19/Dockerfile @@ -172,7 +172,8 @@ ENV PGDATA /var/lib/postgresql/data RUN mkdir -p "$PGDATA" && chown -R postgres:postgres "$PGDATA" && chmod 1777 "$PGDATA" VOLUME /var/lib/postgresql/data -COPY docker-entrypoint.sh /usr/local/bin/ +COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ +RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh ENTRYPOINT ["docker-entrypoint.sh"] # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL diff --git a/14/alpine3.19/docker-ensure-initdb.sh b/14/alpine3.19/docker-ensure-initdb.sh new file mode 100755 index 0000000000..2a9758656e --- /dev/null +++ b/14/alpine3.19/docker-ensure-initdb.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +# +# This script is intended for three main use cases: +# +# 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior +# +# 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution +# (no-op if database is already initialized) +# +# 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use +# (error if database is already initialized) +# + +source /usr/local/bin/docker-entrypoint.sh + +# arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) +if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then + set -- postgres "$@" +fi + +# see also "_main" in "docker-entrypoint.sh" + +docker_setup_env +# setup data directories and permissions (when run as root) +docker_create_db_directories +if [ "$(id -u)" = '0' ]; then + # then restart script as postgres user + exec su-exec postgres "$BASH_SOURCE" "$@" +fi + +# only run initialization on an empty data directory +if [ -z "$DATABASE_ALREADY_EXISTS" ]; then + docker_verify_minimum_env + + # check dir permissions to reduce likelihood of half-initialized database + ls /docker-entrypoint-initdb.d/ > /dev/null + + docker_init_database_dir + pg_setup_hba_conf "$@" + + # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless + # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS + export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" + docker_temp_server_start "$@" + + docker_setup_db + docker_process_init_files /docker-entrypoint-initdb.d/* + + docker_temp_server_stop + unset PGPASSWORD +else + self="$(basename "$0")" + case "$self" in + docker-ensure-initdb.sh) + echo >&2 "$self: note: database already initialized in '$PGDATA'!" + exit 0 + ;; + + docker-enforce-initdb.sh) + echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" + exit 1 + ;; + + *) + echo >&2 "$self: error: unknown file name: $self" + exit 99 + ;; + esac +fi diff --git a/14/alpine3.19/docker-entrypoint.sh b/14/alpine3.19/docker-entrypoint.sh index a383a36487..151d75ef96 100755 --- a/14/alpine3.19/docker-entrypoint.sh +++ b/14/alpine3.19/docker-entrypoint.sh @@ -225,6 +225,7 @@ docker_setup_env() { : "${POSTGRES_HOST_AUTH_METHOD:=}" declare -g DATABASE_ALREADY_EXISTS + : "${DATABASE_ALREADY_EXISTS:=}" # look specifically for PG_VERSION, as it is expected in the DB dir if [ -s "$PGDATA/PG_VERSION" ]; then DATABASE_ALREADY_EXISTS='true' diff --git a/14/bookworm/Dockerfile b/14/bookworm/Dockerfile index e99b2427b9..4905043349 100644 --- a/14/bookworm/Dockerfile +++ b/14/bookworm/Dockerfile @@ -184,7 +184,8 @@ ENV PGDATA /var/lib/postgresql/data RUN mkdir -p "$PGDATA" && chown -R postgres:postgres "$PGDATA" && chmod 1777 "$PGDATA" VOLUME /var/lib/postgresql/data -COPY docker-entrypoint.sh /usr/local/bin/ +COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ +RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh ENTRYPOINT ["docker-entrypoint.sh"] # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL diff --git a/14/bookworm/docker-ensure-initdb.sh b/14/bookworm/docker-ensure-initdb.sh new file mode 100755 index 0000000000..ae1f6b6b90 --- /dev/null +++ b/14/bookworm/docker-ensure-initdb.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +# +# This script is intended for three main use cases: +# +# 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior +# +# 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution +# (no-op if database is already initialized) +# +# 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use +# (error if database is already initialized) +# + +source /usr/local/bin/docker-entrypoint.sh + +# arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) +if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then + set -- postgres "$@" +fi + +# see also "_main" in "docker-entrypoint.sh" + +docker_setup_env +# setup data directories and permissions (when run as root) +docker_create_db_directories +if [ "$(id -u)" = '0' ]; then + # then restart script as postgres user + exec gosu postgres "$BASH_SOURCE" "$@" +fi + +# only run initialization on an empty data directory +if [ -z "$DATABASE_ALREADY_EXISTS" ]; then + docker_verify_minimum_env + + # check dir permissions to reduce likelihood of half-initialized database + ls /docker-entrypoint-initdb.d/ > /dev/null + + docker_init_database_dir + pg_setup_hba_conf "$@" + + # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless + # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS + export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" + docker_temp_server_start "$@" + + docker_setup_db + docker_process_init_files /docker-entrypoint-initdb.d/* + + docker_temp_server_stop + unset PGPASSWORD +else + self="$(basename "$0")" + case "$self" in + docker-ensure-initdb.sh) + echo >&2 "$self: note: database already initialized in '$PGDATA'!" + exit 0 + ;; + + docker-enforce-initdb.sh) + echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" + exit 1 + ;; + + *) + echo >&2 "$self: error: unknown file name: $self" + exit 99 + ;; + esac +fi diff --git a/14/bookworm/docker-entrypoint.sh b/14/bookworm/docker-entrypoint.sh index 0ae0ecf8c2..6d197bc01f 100755 --- a/14/bookworm/docker-entrypoint.sh +++ b/14/bookworm/docker-entrypoint.sh @@ -225,6 +225,7 @@ docker_setup_env() { : "${POSTGRES_HOST_AUTH_METHOD:=}" declare -g DATABASE_ALREADY_EXISTS + : "${DATABASE_ALREADY_EXISTS:=}" # look specifically for PG_VERSION, as it is expected in the DB dir if [ -s "$PGDATA/PG_VERSION" ]; then DATABASE_ALREADY_EXISTS='true' diff --git a/14/bullseye/Dockerfile b/14/bullseye/Dockerfile index d8d3461190..95e24e495a 100644 --- a/14/bullseye/Dockerfile +++ b/14/bullseye/Dockerfile @@ -184,7 +184,8 @@ ENV PGDATA /var/lib/postgresql/data RUN mkdir -p "$PGDATA" && chown -R postgres:postgres "$PGDATA" && chmod 1777 "$PGDATA" VOLUME /var/lib/postgresql/data -COPY docker-entrypoint.sh /usr/local/bin/ +COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ +RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh ENTRYPOINT ["docker-entrypoint.sh"] # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL diff --git a/14/bullseye/docker-ensure-initdb.sh b/14/bullseye/docker-ensure-initdb.sh new file mode 100755 index 0000000000..ae1f6b6b90 --- /dev/null +++ b/14/bullseye/docker-ensure-initdb.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +# +# This script is intended for three main use cases: +# +# 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior +# +# 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution +# (no-op if database is already initialized) +# +# 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use +# (error if database is already initialized) +# + +source /usr/local/bin/docker-entrypoint.sh + +# arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) +if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then + set -- postgres "$@" +fi + +# see also "_main" in "docker-entrypoint.sh" + +docker_setup_env +# setup data directories and permissions (when run as root) +docker_create_db_directories +if [ "$(id -u)" = '0' ]; then + # then restart script as postgres user + exec gosu postgres "$BASH_SOURCE" "$@" +fi + +# only run initialization on an empty data directory +if [ -z "$DATABASE_ALREADY_EXISTS" ]; then + docker_verify_minimum_env + + # check dir permissions to reduce likelihood of half-initialized database + ls /docker-entrypoint-initdb.d/ > /dev/null + + docker_init_database_dir + pg_setup_hba_conf "$@" + + # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless + # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS + export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" + docker_temp_server_start "$@" + + docker_setup_db + docker_process_init_files /docker-entrypoint-initdb.d/* + + docker_temp_server_stop + unset PGPASSWORD +else + self="$(basename "$0")" + case "$self" in + docker-ensure-initdb.sh) + echo >&2 "$self: note: database already initialized in '$PGDATA'!" + exit 0 + ;; + + docker-enforce-initdb.sh) + echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" + exit 1 + ;; + + *) + echo >&2 "$self: error: unknown file name: $self" + exit 99 + ;; + esac +fi diff --git a/14/bullseye/docker-entrypoint.sh b/14/bullseye/docker-entrypoint.sh index 0ae0ecf8c2..6d197bc01f 100755 --- a/14/bullseye/docker-entrypoint.sh +++ b/14/bullseye/docker-entrypoint.sh @@ -225,6 +225,7 @@ docker_setup_env() { : "${POSTGRES_HOST_AUTH_METHOD:=}" declare -g DATABASE_ALREADY_EXISTS + : "${DATABASE_ALREADY_EXISTS:=}" # look specifically for PG_VERSION, as it is expected in the DB dir if [ -s "$PGDATA/PG_VERSION" ]; then DATABASE_ALREADY_EXISTS='true' diff --git a/15/alpine3.18/Dockerfile b/15/alpine3.18/Dockerfile index 8fda3e0adf..7a14aa21fe 100644 --- a/15/alpine3.18/Dockerfile +++ b/15/alpine3.18/Dockerfile @@ -175,7 +175,8 @@ ENV PGDATA /var/lib/postgresql/data RUN mkdir -p "$PGDATA" && chown -R postgres:postgres "$PGDATA" && chmod 1777 "$PGDATA" VOLUME /var/lib/postgresql/data -COPY docker-entrypoint.sh /usr/local/bin/ +COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ +RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh ENTRYPOINT ["docker-entrypoint.sh"] # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL diff --git a/15/alpine3.18/docker-ensure-initdb.sh b/15/alpine3.18/docker-ensure-initdb.sh new file mode 100755 index 0000000000..2a9758656e --- /dev/null +++ b/15/alpine3.18/docker-ensure-initdb.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +# +# This script is intended for three main use cases: +# +# 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior +# +# 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution +# (no-op if database is already initialized) +# +# 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use +# (error if database is already initialized) +# + +source /usr/local/bin/docker-entrypoint.sh + +# arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) +if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then + set -- postgres "$@" +fi + +# see also "_main" in "docker-entrypoint.sh" + +docker_setup_env +# setup data directories and permissions (when run as root) +docker_create_db_directories +if [ "$(id -u)" = '0' ]; then + # then restart script as postgres user + exec su-exec postgres "$BASH_SOURCE" "$@" +fi + +# only run initialization on an empty data directory +if [ -z "$DATABASE_ALREADY_EXISTS" ]; then + docker_verify_minimum_env + + # check dir permissions to reduce likelihood of half-initialized database + ls /docker-entrypoint-initdb.d/ > /dev/null + + docker_init_database_dir + pg_setup_hba_conf "$@" + + # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless + # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS + export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" + docker_temp_server_start "$@" + + docker_setup_db + docker_process_init_files /docker-entrypoint-initdb.d/* + + docker_temp_server_stop + unset PGPASSWORD +else + self="$(basename "$0")" + case "$self" in + docker-ensure-initdb.sh) + echo >&2 "$self: note: database already initialized in '$PGDATA'!" + exit 0 + ;; + + docker-enforce-initdb.sh) + echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" + exit 1 + ;; + + *) + echo >&2 "$self: error: unknown file name: $self" + exit 99 + ;; + esac +fi diff --git a/15/alpine3.18/docker-entrypoint.sh b/15/alpine3.18/docker-entrypoint.sh index a383a36487..151d75ef96 100755 --- a/15/alpine3.18/docker-entrypoint.sh +++ b/15/alpine3.18/docker-entrypoint.sh @@ -225,6 +225,7 @@ docker_setup_env() { : "${POSTGRES_HOST_AUTH_METHOD:=}" declare -g DATABASE_ALREADY_EXISTS + : "${DATABASE_ALREADY_EXISTS:=}" # look specifically for PG_VERSION, as it is expected in the DB dir if [ -s "$PGDATA/PG_VERSION" ]; then DATABASE_ALREADY_EXISTS='true' diff --git a/15/alpine3.19/Dockerfile b/15/alpine3.19/Dockerfile index d419a42cae..77e01e3a9c 100644 --- a/15/alpine3.19/Dockerfile +++ b/15/alpine3.19/Dockerfile @@ -175,7 +175,8 @@ ENV PGDATA /var/lib/postgresql/data RUN mkdir -p "$PGDATA" && chown -R postgres:postgres "$PGDATA" && chmod 1777 "$PGDATA" VOLUME /var/lib/postgresql/data -COPY docker-entrypoint.sh /usr/local/bin/ +COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ +RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh ENTRYPOINT ["docker-entrypoint.sh"] # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL diff --git a/15/alpine3.19/docker-ensure-initdb.sh b/15/alpine3.19/docker-ensure-initdb.sh new file mode 100755 index 0000000000..2a9758656e --- /dev/null +++ b/15/alpine3.19/docker-ensure-initdb.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +# +# This script is intended for three main use cases: +# +# 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior +# +# 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution +# (no-op if database is already initialized) +# +# 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use +# (error if database is already initialized) +# + +source /usr/local/bin/docker-entrypoint.sh + +# arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) +if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then + set -- postgres "$@" +fi + +# see also "_main" in "docker-entrypoint.sh" + +docker_setup_env +# setup data directories and permissions (when run as root) +docker_create_db_directories +if [ "$(id -u)" = '0' ]; then + # then restart script as postgres user + exec su-exec postgres "$BASH_SOURCE" "$@" +fi + +# only run initialization on an empty data directory +if [ -z "$DATABASE_ALREADY_EXISTS" ]; then + docker_verify_minimum_env + + # check dir permissions to reduce likelihood of half-initialized database + ls /docker-entrypoint-initdb.d/ > /dev/null + + docker_init_database_dir + pg_setup_hba_conf "$@" + + # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless + # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS + export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" + docker_temp_server_start "$@" + + docker_setup_db + docker_process_init_files /docker-entrypoint-initdb.d/* + + docker_temp_server_stop + unset PGPASSWORD +else + self="$(basename "$0")" + case "$self" in + docker-ensure-initdb.sh) + echo >&2 "$self: note: database already initialized in '$PGDATA'!" + exit 0 + ;; + + docker-enforce-initdb.sh) + echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" + exit 1 + ;; + + *) + echo >&2 "$self: error: unknown file name: $self" + exit 99 + ;; + esac +fi diff --git a/15/alpine3.19/docker-entrypoint.sh b/15/alpine3.19/docker-entrypoint.sh index a383a36487..151d75ef96 100755 --- a/15/alpine3.19/docker-entrypoint.sh +++ b/15/alpine3.19/docker-entrypoint.sh @@ -225,6 +225,7 @@ docker_setup_env() { : "${POSTGRES_HOST_AUTH_METHOD:=}" declare -g DATABASE_ALREADY_EXISTS + : "${DATABASE_ALREADY_EXISTS:=}" # look specifically for PG_VERSION, as it is expected in the DB dir if [ -s "$PGDATA/PG_VERSION" ]; then DATABASE_ALREADY_EXISTS='true' diff --git a/15/bookworm/Dockerfile b/15/bookworm/Dockerfile index e51062e703..af0da3d468 100644 --- a/15/bookworm/Dockerfile +++ b/15/bookworm/Dockerfile @@ -184,7 +184,8 @@ ENV PGDATA /var/lib/postgresql/data RUN mkdir -p "$PGDATA" && chown -R postgres:postgres "$PGDATA" && chmod 1777 "$PGDATA" VOLUME /var/lib/postgresql/data -COPY docker-entrypoint.sh /usr/local/bin/ +COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ +RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh ENTRYPOINT ["docker-entrypoint.sh"] # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL diff --git a/15/bookworm/docker-ensure-initdb.sh b/15/bookworm/docker-ensure-initdb.sh new file mode 100755 index 0000000000..ae1f6b6b90 --- /dev/null +++ b/15/bookworm/docker-ensure-initdb.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +# +# This script is intended for three main use cases: +# +# 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior +# +# 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution +# (no-op if database is already initialized) +# +# 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use +# (error if database is already initialized) +# + +source /usr/local/bin/docker-entrypoint.sh + +# arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) +if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then + set -- postgres "$@" +fi + +# see also "_main" in "docker-entrypoint.sh" + +docker_setup_env +# setup data directories and permissions (when run as root) +docker_create_db_directories +if [ "$(id -u)" = '0' ]; then + # then restart script as postgres user + exec gosu postgres "$BASH_SOURCE" "$@" +fi + +# only run initialization on an empty data directory +if [ -z "$DATABASE_ALREADY_EXISTS" ]; then + docker_verify_minimum_env + + # check dir permissions to reduce likelihood of half-initialized database + ls /docker-entrypoint-initdb.d/ > /dev/null + + docker_init_database_dir + pg_setup_hba_conf "$@" + + # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless + # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS + export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" + docker_temp_server_start "$@" + + docker_setup_db + docker_process_init_files /docker-entrypoint-initdb.d/* + + docker_temp_server_stop + unset PGPASSWORD +else + self="$(basename "$0")" + case "$self" in + docker-ensure-initdb.sh) + echo >&2 "$self: note: database already initialized in '$PGDATA'!" + exit 0 + ;; + + docker-enforce-initdb.sh) + echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" + exit 1 + ;; + + *) + echo >&2 "$self: error: unknown file name: $self" + exit 99 + ;; + esac +fi diff --git a/15/bookworm/docker-entrypoint.sh b/15/bookworm/docker-entrypoint.sh index 0ae0ecf8c2..6d197bc01f 100755 --- a/15/bookworm/docker-entrypoint.sh +++ b/15/bookworm/docker-entrypoint.sh @@ -225,6 +225,7 @@ docker_setup_env() { : "${POSTGRES_HOST_AUTH_METHOD:=}" declare -g DATABASE_ALREADY_EXISTS + : "${DATABASE_ALREADY_EXISTS:=}" # look specifically for PG_VERSION, as it is expected in the DB dir if [ -s "$PGDATA/PG_VERSION" ]; then DATABASE_ALREADY_EXISTS='true' diff --git a/15/bullseye/Dockerfile b/15/bullseye/Dockerfile index 2bde90139d..2d9db9bb37 100644 --- a/15/bullseye/Dockerfile +++ b/15/bullseye/Dockerfile @@ -184,7 +184,8 @@ ENV PGDATA /var/lib/postgresql/data RUN mkdir -p "$PGDATA" && chown -R postgres:postgres "$PGDATA" && chmod 1777 "$PGDATA" VOLUME /var/lib/postgresql/data -COPY docker-entrypoint.sh /usr/local/bin/ +COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ +RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh ENTRYPOINT ["docker-entrypoint.sh"] # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL diff --git a/15/bullseye/docker-ensure-initdb.sh b/15/bullseye/docker-ensure-initdb.sh new file mode 100755 index 0000000000..ae1f6b6b90 --- /dev/null +++ b/15/bullseye/docker-ensure-initdb.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +# +# This script is intended for three main use cases: +# +# 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior +# +# 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution +# (no-op if database is already initialized) +# +# 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use +# (error if database is already initialized) +# + +source /usr/local/bin/docker-entrypoint.sh + +# arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) +if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then + set -- postgres "$@" +fi + +# see also "_main" in "docker-entrypoint.sh" + +docker_setup_env +# setup data directories and permissions (when run as root) +docker_create_db_directories +if [ "$(id -u)" = '0' ]; then + # then restart script as postgres user + exec gosu postgres "$BASH_SOURCE" "$@" +fi + +# only run initialization on an empty data directory +if [ -z "$DATABASE_ALREADY_EXISTS" ]; then + docker_verify_minimum_env + + # check dir permissions to reduce likelihood of half-initialized database + ls /docker-entrypoint-initdb.d/ > /dev/null + + docker_init_database_dir + pg_setup_hba_conf "$@" + + # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless + # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS + export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" + docker_temp_server_start "$@" + + docker_setup_db + docker_process_init_files /docker-entrypoint-initdb.d/* + + docker_temp_server_stop + unset PGPASSWORD +else + self="$(basename "$0")" + case "$self" in + docker-ensure-initdb.sh) + echo >&2 "$self: note: database already initialized in '$PGDATA'!" + exit 0 + ;; + + docker-enforce-initdb.sh) + echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" + exit 1 + ;; + + *) + echo >&2 "$self: error: unknown file name: $self" + exit 99 + ;; + esac +fi diff --git a/15/bullseye/docker-entrypoint.sh b/15/bullseye/docker-entrypoint.sh index 0ae0ecf8c2..6d197bc01f 100755 --- a/15/bullseye/docker-entrypoint.sh +++ b/15/bullseye/docker-entrypoint.sh @@ -225,6 +225,7 @@ docker_setup_env() { : "${POSTGRES_HOST_AUTH_METHOD:=}" declare -g DATABASE_ALREADY_EXISTS + : "${DATABASE_ALREADY_EXISTS:=}" # look specifically for PG_VERSION, as it is expected in the DB dir if [ -s "$PGDATA/PG_VERSION" ]; then DATABASE_ALREADY_EXISTS='true' diff --git a/16/alpine3.18/Dockerfile b/16/alpine3.18/Dockerfile index c93ecdb229..c96c944ca2 100644 --- a/16/alpine3.18/Dockerfile +++ b/16/alpine3.18/Dockerfile @@ -174,7 +174,8 @@ ENV PGDATA /var/lib/postgresql/data RUN mkdir -p "$PGDATA" && chown -R postgres:postgres "$PGDATA" && chmod 1777 "$PGDATA" VOLUME /var/lib/postgresql/data -COPY docker-entrypoint.sh /usr/local/bin/ +COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ +RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh ENTRYPOINT ["docker-entrypoint.sh"] # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL diff --git a/16/alpine3.18/docker-ensure-initdb.sh b/16/alpine3.18/docker-ensure-initdb.sh new file mode 100755 index 0000000000..2a9758656e --- /dev/null +++ b/16/alpine3.18/docker-ensure-initdb.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +# +# This script is intended for three main use cases: +# +# 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior +# +# 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution +# (no-op if database is already initialized) +# +# 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use +# (error if database is already initialized) +# + +source /usr/local/bin/docker-entrypoint.sh + +# arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) +if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then + set -- postgres "$@" +fi + +# see also "_main" in "docker-entrypoint.sh" + +docker_setup_env +# setup data directories and permissions (when run as root) +docker_create_db_directories +if [ "$(id -u)" = '0' ]; then + # then restart script as postgres user + exec su-exec postgres "$BASH_SOURCE" "$@" +fi + +# only run initialization on an empty data directory +if [ -z "$DATABASE_ALREADY_EXISTS" ]; then + docker_verify_minimum_env + + # check dir permissions to reduce likelihood of half-initialized database + ls /docker-entrypoint-initdb.d/ > /dev/null + + docker_init_database_dir + pg_setup_hba_conf "$@" + + # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless + # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS + export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" + docker_temp_server_start "$@" + + docker_setup_db + docker_process_init_files /docker-entrypoint-initdb.d/* + + docker_temp_server_stop + unset PGPASSWORD +else + self="$(basename "$0")" + case "$self" in + docker-ensure-initdb.sh) + echo >&2 "$self: note: database already initialized in '$PGDATA'!" + exit 0 + ;; + + docker-enforce-initdb.sh) + echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" + exit 1 + ;; + + *) + echo >&2 "$self: error: unknown file name: $self" + exit 99 + ;; + esac +fi diff --git a/16/alpine3.18/docker-entrypoint.sh b/16/alpine3.18/docker-entrypoint.sh index a383a36487..151d75ef96 100755 --- a/16/alpine3.18/docker-entrypoint.sh +++ b/16/alpine3.18/docker-entrypoint.sh @@ -225,6 +225,7 @@ docker_setup_env() { : "${POSTGRES_HOST_AUTH_METHOD:=}" declare -g DATABASE_ALREADY_EXISTS + : "${DATABASE_ALREADY_EXISTS:=}" # look specifically for PG_VERSION, as it is expected in the DB dir if [ -s "$PGDATA/PG_VERSION" ]; then DATABASE_ALREADY_EXISTS='true' diff --git a/16/alpine3.19/Dockerfile b/16/alpine3.19/Dockerfile index 0f98b442c0..9228071a3e 100644 --- a/16/alpine3.19/Dockerfile +++ b/16/alpine3.19/Dockerfile @@ -174,7 +174,8 @@ ENV PGDATA /var/lib/postgresql/data RUN mkdir -p "$PGDATA" && chown -R postgres:postgres "$PGDATA" && chmod 1777 "$PGDATA" VOLUME /var/lib/postgresql/data -COPY docker-entrypoint.sh /usr/local/bin/ +COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ +RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh ENTRYPOINT ["docker-entrypoint.sh"] # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL diff --git a/16/alpine3.19/docker-ensure-initdb.sh b/16/alpine3.19/docker-ensure-initdb.sh new file mode 100755 index 0000000000..2a9758656e --- /dev/null +++ b/16/alpine3.19/docker-ensure-initdb.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +# +# This script is intended for three main use cases: +# +# 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior +# +# 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution +# (no-op if database is already initialized) +# +# 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use +# (error if database is already initialized) +# + +source /usr/local/bin/docker-entrypoint.sh + +# arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) +if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then + set -- postgres "$@" +fi + +# see also "_main" in "docker-entrypoint.sh" + +docker_setup_env +# setup data directories and permissions (when run as root) +docker_create_db_directories +if [ "$(id -u)" = '0' ]; then + # then restart script as postgres user + exec su-exec postgres "$BASH_SOURCE" "$@" +fi + +# only run initialization on an empty data directory +if [ -z "$DATABASE_ALREADY_EXISTS" ]; then + docker_verify_minimum_env + + # check dir permissions to reduce likelihood of half-initialized database + ls /docker-entrypoint-initdb.d/ > /dev/null + + docker_init_database_dir + pg_setup_hba_conf "$@" + + # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless + # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS + export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" + docker_temp_server_start "$@" + + docker_setup_db + docker_process_init_files /docker-entrypoint-initdb.d/* + + docker_temp_server_stop + unset PGPASSWORD +else + self="$(basename "$0")" + case "$self" in + docker-ensure-initdb.sh) + echo >&2 "$self: note: database already initialized in '$PGDATA'!" + exit 0 + ;; + + docker-enforce-initdb.sh) + echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" + exit 1 + ;; + + *) + echo >&2 "$self: error: unknown file name: $self" + exit 99 + ;; + esac +fi diff --git a/16/alpine3.19/docker-entrypoint.sh b/16/alpine3.19/docker-entrypoint.sh index a383a36487..151d75ef96 100755 --- a/16/alpine3.19/docker-entrypoint.sh +++ b/16/alpine3.19/docker-entrypoint.sh @@ -225,6 +225,7 @@ docker_setup_env() { : "${POSTGRES_HOST_AUTH_METHOD:=}" declare -g DATABASE_ALREADY_EXISTS + : "${DATABASE_ALREADY_EXISTS:=}" # look specifically for PG_VERSION, as it is expected in the DB dir if [ -s "$PGDATA/PG_VERSION" ]; then DATABASE_ALREADY_EXISTS='true' diff --git a/16/bookworm/Dockerfile b/16/bookworm/Dockerfile index 684c6ee36a..15369fd019 100644 --- a/16/bookworm/Dockerfile +++ b/16/bookworm/Dockerfile @@ -184,7 +184,8 @@ ENV PGDATA /var/lib/postgresql/data RUN mkdir -p "$PGDATA" && chown -R postgres:postgres "$PGDATA" && chmod 1777 "$PGDATA" VOLUME /var/lib/postgresql/data -COPY docker-entrypoint.sh /usr/local/bin/ +COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ +RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh ENTRYPOINT ["docker-entrypoint.sh"] # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL diff --git a/16/bookworm/docker-ensure-initdb.sh b/16/bookworm/docker-ensure-initdb.sh new file mode 100755 index 0000000000..ae1f6b6b90 --- /dev/null +++ b/16/bookworm/docker-ensure-initdb.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +# +# This script is intended for three main use cases: +# +# 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior +# +# 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution +# (no-op if database is already initialized) +# +# 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use +# (error if database is already initialized) +# + +source /usr/local/bin/docker-entrypoint.sh + +# arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) +if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then + set -- postgres "$@" +fi + +# see also "_main" in "docker-entrypoint.sh" + +docker_setup_env +# setup data directories and permissions (when run as root) +docker_create_db_directories +if [ "$(id -u)" = '0' ]; then + # then restart script as postgres user + exec gosu postgres "$BASH_SOURCE" "$@" +fi + +# only run initialization on an empty data directory +if [ -z "$DATABASE_ALREADY_EXISTS" ]; then + docker_verify_minimum_env + + # check dir permissions to reduce likelihood of half-initialized database + ls /docker-entrypoint-initdb.d/ > /dev/null + + docker_init_database_dir + pg_setup_hba_conf "$@" + + # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless + # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS + export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" + docker_temp_server_start "$@" + + docker_setup_db + docker_process_init_files /docker-entrypoint-initdb.d/* + + docker_temp_server_stop + unset PGPASSWORD +else + self="$(basename "$0")" + case "$self" in + docker-ensure-initdb.sh) + echo >&2 "$self: note: database already initialized in '$PGDATA'!" + exit 0 + ;; + + docker-enforce-initdb.sh) + echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" + exit 1 + ;; + + *) + echo >&2 "$self: error: unknown file name: $self" + exit 99 + ;; + esac +fi diff --git a/16/bookworm/docker-entrypoint.sh b/16/bookworm/docker-entrypoint.sh index 0ae0ecf8c2..6d197bc01f 100755 --- a/16/bookworm/docker-entrypoint.sh +++ b/16/bookworm/docker-entrypoint.sh @@ -225,6 +225,7 @@ docker_setup_env() { : "${POSTGRES_HOST_AUTH_METHOD:=}" declare -g DATABASE_ALREADY_EXISTS + : "${DATABASE_ALREADY_EXISTS:=}" # look specifically for PG_VERSION, as it is expected in the DB dir if [ -s "$PGDATA/PG_VERSION" ]; then DATABASE_ALREADY_EXISTS='true' diff --git a/16/bullseye/Dockerfile b/16/bullseye/Dockerfile index ecc31fc106..b132cc211b 100644 --- a/16/bullseye/Dockerfile +++ b/16/bullseye/Dockerfile @@ -184,7 +184,8 @@ ENV PGDATA /var/lib/postgresql/data RUN mkdir -p "$PGDATA" && chown -R postgres:postgres "$PGDATA" && chmod 1777 "$PGDATA" VOLUME /var/lib/postgresql/data -COPY docker-entrypoint.sh /usr/local/bin/ +COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ +RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh ENTRYPOINT ["docker-entrypoint.sh"] # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL diff --git a/16/bullseye/docker-ensure-initdb.sh b/16/bullseye/docker-ensure-initdb.sh new file mode 100755 index 0000000000..ae1f6b6b90 --- /dev/null +++ b/16/bullseye/docker-ensure-initdb.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +# +# This script is intended for three main use cases: +# +# 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior +# +# 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution +# (no-op if database is already initialized) +# +# 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use +# (error if database is already initialized) +# + +source /usr/local/bin/docker-entrypoint.sh + +# arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) +if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then + set -- postgres "$@" +fi + +# see also "_main" in "docker-entrypoint.sh" + +docker_setup_env +# setup data directories and permissions (when run as root) +docker_create_db_directories +if [ "$(id -u)" = '0' ]; then + # then restart script as postgres user + exec gosu postgres "$BASH_SOURCE" "$@" +fi + +# only run initialization on an empty data directory +if [ -z "$DATABASE_ALREADY_EXISTS" ]; then + docker_verify_minimum_env + + # check dir permissions to reduce likelihood of half-initialized database + ls /docker-entrypoint-initdb.d/ > /dev/null + + docker_init_database_dir + pg_setup_hba_conf "$@" + + # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless + # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS + export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" + docker_temp_server_start "$@" + + docker_setup_db + docker_process_init_files /docker-entrypoint-initdb.d/* + + docker_temp_server_stop + unset PGPASSWORD +else + self="$(basename "$0")" + case "$self" in + docker-ensure-initdb.sh) + echo >&2 "$self: note: database already initialized in '$PGDATA'!" + exit 0 + ;; + + docker-enforce-initdb.sh) + echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" + exit 1 + ;; + + *) + echo >&2 "$self: error: unknown file name: $self" + exit 99 + ;; + esac +fi diff --git a/16/bullseye/docker-entrypoint.sh b/16/bullseye/docker-entrypoint.sh index 0ae0ecf8c2..6d197bc01f 100755 --- a/16/bullseye/docker-entrypoint.sh +++ b/16/bullseye/docker-entrypoint.sh @@ -225,6 +225,7 @@ docker_setup_env() { : "${POSTGRES_HOST_AUTH_METHOD:=}" declare -g DATABASE_ALREADY_EXISTS + : "${DATABASE_ALREADY_EXISTS:=}" # look specifically for PG_VERSION, as it is expected in the DB dir if [ -s "$PGDATA/PG_VERSION" ]; then DATABASE_ALREADY_EXISTS='true' diff --git a/Dockerfile-alpine.template b/Dockerfile-alpine.template index efbccde00e..23e53677e1 100644 --- a/Dockerfile-alpine.template +++ b/Dockerfile-alpine.template @@ -194,7 +194,8 @@ ENV PGDATA /var/lib/postgresql/data RUN mkdir -p "$PGDATA" && chown -R postgres:postgres "$PGDATA" && chmod 1777 "$PGDATA" VOLUME /var/lib/postgresql/data -COPY docker-entrypoint.sh /usr/local/bin/ +COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ +RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh ENTRYPOINT ["docker-entrypoint.sh"] # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL diff --git a/Dockerfile-debian.template b/Dockerfile-debian.template index 3d1884be00..588fced34d 100644 --- a/Dockerfile-debian.template +++ b/Dockerfile-debian.template @@ -182,7 +182,8 @@ ENV PGDATA /var/lib/postgresql/data RUN mkdir -p "$PGDATA" && chown -R postgres:postgres "$PGDATA" && chmod 1777 "$PGDATA" VOLUME /var/lib/postgresql/data -COPY docker-entrypoint.sh /usr/local/bin/ +COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ +RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh ENTRYPOINT ["docker-entrypoint.sh"] # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL diff --git a/apply-templates.sh b/apply-templates.sh index 7b6dc1763d..fb375d379f 100755 --- a/apply-templates.sh +++ b/apply-templates.sh @@ -52,12 +52,12 @@ for version; do echo "processing $dir ..." - cp -a docker-entrypoint.sh "$dir/" + cp -a docker-entrypoint.sh docker-ensure-initdb.sh "$dir/" case "$variant" in alpine*) template='Dockerfile-alpine.template' - sed -i -e 's/gosu/su-exec/g' "$dir/docker-entrypoint.sh" + sed -i -e 's/gosu/su-exec/g' "$dir/docker-entrypoint.sh" "$dir/docker-ensure-initdb.sh" ;; *) template='Dockerfile-debian.template' diff --git a/docker-ensure-initdb.sh b/docker-ensure-initdb.sh new file mode 100755 index 0000000000..ae1f6b6b90 --- /dev/null +++ b/docker-ensure-initdb.sh @@ -0,0 +1,71 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +# +# This script is intended for three main use cases: +# +# 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior +# +# 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution +# (no-op if database is already initialized) +# +# 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use +# (error if database is already initialized) +# + +source /usr/local/bin/docker-entrypoint.sh + +# arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) +if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then + set -- postgres "$@" +fi + +# see also "_main" in "docker-entrypoint.sh" + +docker_setup_env +# setup data directories and permissions (when run as root) +docker_create_db_directories +if [ "$(id -u)" = '0' ]; then + # then restart script as postgres user + exec gosu postgres "$BASH_SOURCE" "$@" +fi + +# only run initialization on an empty data directory +if [ -z "$DATABASE_ALREADY_EXISTS" ]; then + docker_verify_minimum_env + + # check dir permissions to reduce likelihood of half-initialized database + ls /docker-entrypoint-initdb.d/ > /dev/null + + docker_init_database_dir + pg_setup_hba_conf "$@" + + # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless + # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS + export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" + docker_temp_server_start "$@" + + docker_setup_db + docker_process_init_files /docker-entrypoint-initdb.d/* + + docker_temp_server_stop + unset PGPASSWORD +else + self="$(basename "$0")" + case "$self" in + docker-ensure-initdb.sh) + echo >&2 "$self: note: database already initialized in '$PGDATA'!" + exit 0 + ;; + + docker-enforce-initdb.sh) + echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" + exit 1 + ;; + + *) + echo >&2 "$self: error: unknown file name: $self" + exit 99 + ;; + esac +fi diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index 0ae0ecf8c2..6d197bc01f 100755 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -225,6 +225,7 @@ docker_setup_env() { : "${POSTGRES_HOST_AUTH_METHOD:=}" declare -g DATABASE_ALREADY_EXISTS + : "${DATABASE_ALREADY_EXISTS:=}" # look specifically for PG_VERSION, as it is expected in the DB dir if [ -s "$PGDATA/PG_VERSION" ]; then DATABASE_ALREADY_EXISTS='true'