1- #! /bin/bash
2- set -e
1+ #! /usr/bin/env bash
2+ set -Eeo pipefail
3+ # TODO swap to -Eeuo pipefail above (after handling all potentially-unset variables)
34
45# usage: file_env VAR [DEFAULT]
56# ie: file_env 'XYZ_DB_PASSWORD' 'example'
@@ -27,26 +28,75 @@ if [ "${1:0:1}" = '-' ]; then
2728 set -- postgres " $@ "
2829fi
2930
30- if [ " $1 " = ' postgres' ]; then
31+ # allow the container to be started with `--user`
32+ if [ " $1 " = ' postgres' ] && [ " $( id -u) " = ' 0' ]; then
3133 mkdir -p " $PGDATA "
32- chmod 700 " $PGDATA "
3334 chown -R postgres " $PGDATA "
35+ chmod 700 " $PGDATA "
3436
35- mkdir -p /run/postgresql
36- chmod g+s /run/postgresql
37- chown -R postgres /run/postgresql
37+ mkdir -p /var/run/postgresql
38+ chown -R postgres /var/run/postgresql
39+ chmod 775 /var/run/postgresql
40+
41+ # Create the transaction log directory before initdb is run (below) so the directory is owned by the correct user
42+ if [ " $POSTGRES_INITDB_WALDIR " ]; then
43+ mkdir -p " $POSTGRES_INITDB_WALDIR "
44+ chown -R postgres " $POSTGRES_INITDB_WALDIR "
45+ chmod 700 " $POSTGRES_INITDB_WALDIR "
46+ fi
47+
48+ exec gosu postgres " $BASH_SOURCE " " $@ "
49+ fi
50+
51+ if [ " $1 " = ' postgres' ]; then
52+ mkdir -p " $PGDATA "
53+ chown -R " $( id -u) " " $PGDATA " 2> /dev/null || :
54+ chmod 700 " $PGDATA " 2> /dev/null || :
3855
3956 # look specifically for PG_VERSION, as it is expected in the DB dir
4057 if [ ! -s " $PGDATA /PG_VERSION" ]; then
58+ # "initdb" is particular about the current user existing in "/etc/passwd", so we use "nss_wrapper" to fake that if necessary
59+ # see https://github.com/docker-library/postgres/pull/253, https://github.com/docker-library/postgres/issues/359, https://cwrap.org/nss_wrapper.html
60+ if ! getent passwd " $( id -u) " & > /dev/null && [ -e /usr/lib/libnss_wrapper.so ]; then
61+ export LD_PRELOAD=' /usr/lib/libnss_wrapper.so'
62+ export NSS_WRAPPER_PASSWD=" $( mktemp) "
63+ export NSS_WRAPPER_GROUP=" $( mktemp) "
64+ echo " postgres:x:$( id -u) :$( id -g) :PostgreSQL:$PGDATA :/bin/false" > " $NSS_WRAPPER_PASSWD "
65+ echo " postgres:x:$( id -g) :" > " $NSS_WRAPPER_GROUP "
66+ fi
67+
68+ file_env ' POSTGRES_USER' ' postgres'
69+ file_env ' POSTGRES_PASSWORD'
70+
4171 file_env ' POSTGRES_INITDB_ARGS'
42- eval " gosu postgres initdb $POSTGRES_INITDB_ARGS "
72+ if [ " $POSTGRES_INITDB_WALDIR " ]; then
73+ export POSTGRES_INITDB_ARGS=" $POSTGRES_INITDB_ARGS --waldir $POSTGRES_INITDB_WALDIR "
74+ fi
75+ eval ' initdb --username="$POSTGRES_USER" --pwfile=<(echo "$POSTGRES_PASSWORD") ' " $POSTGRES_INITDB_ARGS "
76+
77+ # unset/cleanup "nss_wrapper" bits
78+ if [ " ${LD_PRELOAD:- } " = ' /usr/lib/libnss_wrapper.so' ]; then
79+ rm -f " $NSS_WRAPPER_PASSWD " " $NSS_WRAPPER_GROUP "
80+ unset LD_PRELOAD NSS_WRAPPER_PASSWD NSS_WRAPPER_GROUP
81+ fi
4382
4483 # check password first so we can output the warning before postgres
4584 # messes it up
46- file_env ' POSTGRES_PASSWORD'
47- if [ " $POSTGRES_PASSWORD " ]; then
48- pass=" PASSWORD '$POSTGRES_PASSWORD '"
85+ if [ -n " $POSTGRES_PASSWORD " ]; then
4986 authMethod=md5
87+
88+ if [ " ${# POSTGRES_PASSWORD} " -ge 100 ]; then
89+ cat >&2 << -'EOWARN '
90+
91+ WARNING: The supplied POSTGRES_PASSWORD is 100+ characters.
92+
93+ This will not work if used via PGPASSWORD with "psql".
94+
95+ https://www.postgresql.org/message-id/flat/E1Rqxp2-0004Qt-PL%40wrigleys.postgresql.org (BUG #6412)
96+ https://github.com/docker-library/postgres/issues/507
97+
98+ EOWARN
99+ fi
50100 else
51101 # The - option suppresses leading tabs but *not* spaces. :)
52102 cat >&2 << -'EOWARN '
@@ -57,67 +107,70 @@ if [ "$1" = 'postgres' ]; then
57107 Docker's default configuration, this is
58108 effectively any other container on the same
59109 system.
110+
60111 Use "-e POSTGRES_PASSWORD=password" to set
61112 it in "docker run".
62113 ****************************************************
63114 EOWARN
64115
65- pass=
66116 authMethod=trust
67117 fi
68118
69- { echo ; echo " host all all all $authMethod " ; } | gosu postgres tee -a " $PGDATA /pg_hba.conf" > /dev/null
119+ {
120+ echo
121+ echo " host all all all $authMethod "
122+ } >> " $PGDATA /pg_hba.conf"
70123
71- # internal start of server in order to allow set-up using psql-client
124+ # internal start of server in order to allow set-up using psql-client
72125 # does not listen on external TCP/IP and waits until start finishes
73- gosu postgres pg_ctl -D " $PGDATA " \
74- -o " -c listen_addresses='localhost'" \
126+ PGUSER=" ${PGUSER:- $POSTGRES_USER } " \
127+ pg_ctl -D " $PGDATA " \
128+ -o " -c listen_addresses=''" \
75129 -w start
76130
77- file_env ' POSTGRES_USER' ' postgres'
78131 file_env ' POSTGRES_DB' " $POSTGRES_USER "
79132
80- psql=( psql -v ON_ERROR_STOP=1 )
133+ export PGPASSWORD=" ${PGPASSWORD:- $POSTGRES_PASSWORD } "
134+ psql=( psql -v ON_ERROR_STOP=1 --username " $POSTGRES_USER " --no-password )
81135
82136 if [ " $POSTGRES_DB " != ' postgres' ]; then
83- " ${psql[@]} " --username postgres << -EOSQL
84- CREATE DATABASE " $POSTGRES_DB " ;
137+ " ${psql[@]} " --dbname postgres --set db= " $POSTGRES_DB " << -' EOSQL '
138+ CREATE DATABASE :"db " ;
85139 EOSQL
86140 echo
87141 fi
88-
89- if [ " $POSTGRES_USER " = ' postgres' ]; then
90- op=' ALTER'
91- else
92- op=' CREATE'
93- fi
94- " ${psql[@]} " --username postgres << -EOSQL
95- $op USER "$POSTGRES_USER " WITH SUPERUSER $pass ;
96- EOSQL
97- echo
98-
99- psql+=( --username " $POSTGRES_USER " --dbname " $POSTGRES_DB " )
142+ psql+=( --dbname " $POSTGRES_DB " )
100143
101144 echo
102145 for f in /docker-entrypoint-initdb.d/* ; do
103146 case " $f " in
104- * .sh) echo " $0 : running $f " ; . " $f " ;;
147+ * .sh)
148+ # https://github.com/docker-library/postgres/issues/450#issuecomment-393167936
149+ # https://github.com/docker-library/postgres/pull/452
150+ if [ -x " $f " ]; then
151+ echo " $0 : running $f "
152+ " $f "
153+ else
154+ echo " $0 : sourcing $f "
155+ . " $f "
156+ fi
157+ ;;
105158 * .sql) echo " $0 : running $f " ; " ${psql[@]} " -f " $f " ; echo ;;
106159 * .sql.gz) echo " $0 : running $f " ; gunzip -c " $f " | " ${psql[@]} " ; echo ;;
107160 * ) echo " $0 : ignoring $f " ;;
108161 esac
109162 echo
110163 done
111164
112- gosu postgres pg_ctl -D " $PGDATA " -m fast -w stop
165+ PGUSER=" ${PGUSER:- $POSTGRES_USER } " \
166+ pg_ctl -D " $PGDATA " -m fast -w stop
167+
168+ unset PGPASSWORD
113169
114170 echo
115171 echo ' PostgreSQL init process complete; ready for start up.'
116172 echo
117173 fi
118-
119- exec gosu postgres " $@ "
120174fi
121175
122176exec " $@ "
123-
0 commit comments