| #!/usr/bin/env bash |
| set -Eeo pipefail |
| # TODO swap to -Eeuo pipefail above (after handling all potentially-unset variables) |
| |
| # usage: file_env VAR [DEFAULT] |
| # ie: file_env 'XYZ_DB_PASSWORD' 'example' |
| # (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of |
| # "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature) |
| file_env() { |
| local var="$1" |
| local fileVar="${var}_FILE" |
| local def="${2:-}" |
| if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then |
| echo >&2 "error: both $var and $fileVar are set (but are exclusive)" |
| exit 1 |
| fi |
| local val="$def" |
| if [ "${!var:-}" ]; then |
| val="${!var}" |
| elif [ "${!fileVar:-}" ]; then |
| val="$(< "${!fileVar}")" |
| fi |
| export "$var"="$val" |
| unset "$fileVar" |
| } |
| |
| if [ "${1:0:1}" = '-' ]; then |
| set -- postgres "$@" |
| fi |
| |
| # allow the container to be started with `--user` |
| if [ "$1" = 'postgres' ] && [ "$(id -u)" = '0' ]; then |
| mkdir -p "$PGDATA" |
| chown -R postgres "$PGDATA" |
| chmod 700 "$PGDATA" |
| |
| mkdir -p /var/run/postgresql |
| chown -R postgres /var/run/postgresql |
| chmod 775 /var/run/postgresql |
| |
| # Create the transaction log directory before initdb is run (below) so the directory is owned by the correct user |
| if [ "$POSTGRES_INITDB_WALDIR" ]; then |
| mkdir -p "$POSTGRES_INITDB_WALDIR" |
| chown -R postgres "$POSTGRES_INITDB_WALDIR" |
| chmod 700 "$POSTGRES_INITDB_WALDIR" |
| fi |
| |
| exec gosu postgres "$BASH_SOURCE" "$@" |
| fi |
| |
| if [ "$1" = 'postgres' ]; then |
| mkdir -p "$PGDATA" |
| chown -R "$(id -u)" "$PGDATA" 2>/dev/null || : |
| chmod 700 "$PGDATA" 2>/dev/null || : |
| |
| # look specifically for PG_VERSION, as it is expected in the DB dir |
| if [ ! -s "$PGDATA/PG_VERSION" ]; then |
| # "initdb" is particular about the current user existing in "/etc/passwd", so we use "nss_wrapper" to fake that if necessary |
| # see https://github.com/docker-library/postgres/pull/253, https://github.com/docker-library/postgres/issues/359, https://cwrap.org/nss_wrapper.html |
| if ! getent passwd "$(id -u)" &> /dev/null && [ -e /usr/lib/libnss_wrapper.so ]; then |
| export LD_PRELOAD='/usr/lib/libnss_wrapper.so' |
| export NSS_WRAPPER_PASSWD="$(mktemp)" |
| export NSS_WRAPPER_GROUP="$(mktemp)" |
| echo "postgres:x:$(id -u):$(id -g):PostgreSQL:$PGDATA:/bin/false" > "$NSS_WRAPPER_PASSWD" |
| echo "postgres:x:$(id -g):" > "$NSS_WRAPPER_GROUP" |
| fi |
| |
| file_env 'POSTGRES_USER' 'postgres' |
| file_env 'POSTGRES_PASSWORD' |
| |
| file_env 'POSTGRES_INITDB_ARGS' |
| if [ "$POSTGRES_INITDB_WALDIR" ]; then |
| export POSTGRES_INITDB_ARGS="$POSTGRES_INITDB_ARGS --waldir $POSTGRES_INITDB_WALDIR" |
| fi |
| eval 'initdb --username="$POSTGRES_USER" --pwfile=<(echo "$POSTGRES_PASSWORD") '"$POSTGRES_INITDB_ARGS" |
| |
| # unset/cleanup "nss_wrapper" bits |
| if [ "${LD_PRELOAD:-}" = '/usr/lib/libnss_wrapper.so' ]; then |
| rm -f "$NSS_WRAPPER_PASSWD" "$NSS_WRAPPER_GROUP" |
| unset LD_PRELOAD NSS_WRAPPER_PASSWD NSS_WRAPPER_GROUP |
| fi |
| |
| # check password first so we can output the warning before postgres |
| # messes it up |
| if [ -n "$POSTGRES_PASSWORD" ]; then |
| authMethod=md5 |
| |
| if [ "${#POSTGRES_PASSWORD}" -ge 100 ]; then |
| cat >&2 <<-'EOWARN' |
| |
| WARNING: The supplied POSTGRES_PASSWORD is 100+ characters. |
| |
| This will not work if used via PGPASSWORD with "psql". |
| |
| https://www.postgresql.org/message-id/flat/E1Rqxp2-0004Qt-PL%40wrigleys.postgresql.org (BUG #6412) |
| https://github.com/docker-library/postgres/issues/507 |
| |
| EOWARN |
| fi |
| else |
| # The - option suppresses leading tabs but *not* spaces. :) |
| cat >&2 <<-'EOWARN' |
| **************************************************** |
| WARNING: No password has been set for the database. |
| This will allow anyone with access to the |
| Postgres port to access your database. In |
| Docker's default configuration, this is |
| effectively any other container on the same |
| system. |
| |
| Use "-e POSTGRES_PASSWORD=password" to set |
| it in "docker run". |
| **************************************************** |
| EOWARN |
| |
| authMethod=trust |
| fi |
| |
| { |
| echo |
| echo "host all all all $authMethod" |
| } >> "$PGDATA/pg_hba.conf" |
| |
| # internal start of server in order to allow set-up using psql-client |
| # does not listen on external TCP/IP and waits until start finishes |
| PGUSER="${PGUSER:-$POSTGRES_USER}" \ |
| pg_ctl -D "$PGDATA" \ |
| -o "-c listen_addresses=''" \ |
| -w start |
| |
| file_env 'POSTGRES_DB' "$POSTGRES_USER" |
| |
| export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" |
| psql=( psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --no-password ) |
| |
| if [ "$POSTGRES_DB" != 'postgres' ]; then |
| "${psql[@]}" --dbname postgres --set db="$POSTGRES_DB" <<-'EOSQL' |
| CREATE DATABASE :"db" ; |
| EOSQL |
| echo |
| fi |
| psql+=( --dbname "$POSTGRES_DB" ) |
| |
| echo |
| for f in ./ci/sql/*; do |
| case "$f" in |
| *.sh) |
| # https://github.com/docker-library/postgres/issues/450#issuecomment-393167936 |
| # https://github.com/docker-library/postgres/pull/452 |
| if [ -x "$f" ]; then |
| echo "$0: running $f" |
| "$f" |
| else |
| echo "$0: sourcing $f" |
| . "$f" |
| fi |
| ;; |
| *.sql) echo "$0: running $f"; "${psql[@]}" -f "$f"; echo ;; |
| *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${psql[@]}"; echo ;; |
| *) echo "$0: ignoring $f" ;; |
| esac |
| echo |
| done |
| |
| PGUSER="${PGUSER:-$POSTGRES_USER}" \ |
| pg_ctl -D "$PGDATA" -m fast -w stop |
| |
| unset PGPASSWORD |
| |
| echo |
| echo 'PostgreSQL init process complete; ready for start up.' |
| echo |
| fi |
| fi |