@@ -56,6 +56,9 @@ docker_create_db_directories() {
5656}
5757
5858# initialize empty PGDATA directory with new database via 'initdb'
59+ # arguments to `initdb` can be passed via POSTGRES_INITDB_ARGS or as arguments to this function
60+ # `initdb` automatically creates the "postgres", "template0", and "template1" dbnames
61+ # this is also where the database user is created, specified by `POSTGRES_USER` env
5962docker_init_database_dir () {
6063 # "initdb" is particular about the current user existing in "/etc/passwd", so we use "nss_wrapper" to fake that if necessary
6164 # see https://github.com/docker-library/postgres/pull/253, https://github.com/docker-library/postgres/issues/359, https://cwrap.org/nss_wrapper.html
@@ -67,12 +70,11 @@ docker_init_database_dir() {
6770 echo " postgres:x:$( id -g) :" > " $NSS_WRAPPER_GROUP "
6871 fi
6972
70- file_env ' POSTGRES_INITDB_ARGS'
7173 if [ " $POSTGRES_INITDB_WALDIR " ]; then
72- export POSTGRES_INITDB_ARGS= " $POSTGRES_INITDB_ARGS --waldir $POSTGRES_INITDB_WALDIR "
74+ set -- --waldir " $POSTGRES_INITDB_WALDIR " " $@ "
7375 fi
7476
75- eval ' initdb --username="$POSTGRES_USER" --pwfile=<(echo "$POSTGRES_PASSWORD") ' " $POSTGRES_INITDB_ARGS "
77+ eval ' initdb --username="$POSTGRES_USER" --pwfile=<(echo "$POSTGRES_PASSWORD") ' " $POSTGRES_INITDB_ARGS " ' "$@" '
7678
7779 # unset/cleanup "nss_wrapper" bits
7880 if [ " ${LD_PRELOAD:- } " = ' /usr/lib/libnss_wrapper.so' ]; then
@@ -116,15 +118,16 @@ docker_verify_minimum_env() {
116118 fi
117119}
118120
119- # run, source, or read files from /docker-entrypoint-initdb.d (or specified directory)
121+ # usage: docker_process_init_files [file [file [...]]]
122+ # ie: docker_process_init_files /always-initdb.d/*
123+ # process initializer files, based on file extensions and permissions
120124docker_process_init_files () {
121125 # psql here for backwards compatiblilty "${psql[@]}"
122126 psql=( docker_process_sql )
123127
124- local initDir=" ${1:-/ docker-entrypoint-initdb.d} "
125-
126128 echo
127- for f in " ${initDir%/ } " /* ; do
129+ local f
130+ for f; do
128131 case " $f " in
129132 * .sh)
130133 # https://github.com/docker-library/postgres/issues/450#issuecomment-393167936
@@ -145,7 +148,11 @@ docker_process_init_files() {
145148 done
146149}
147150
148- # run `psql` with proper arguments for user and db
151+ # Execute sql script, passed via stdin (or -f flag of pqsl)
152+ # usage: docker_process_sql [psql-cli-args]
153+ # ie: docker_process_sql --dbname=mydb <<<'INSERT ...'
154+ # ie: docker_process_sql -f my-file.sql
155+ # ie: docker_process_sql <my-file.sql
149156docker_process_sql () {
150157 local query_runner=( psql -v ON_ERROR_STOP=1 --username " $POSTGRES_USER " --no-password )
151158 if [ -n " $POSTGRES_DB " ]; then
@@ -155,8 +162,8 @@ docker_process_sql() {
155162 " ${query_runner[@]} " " $@ "
156163}
157164
158- # create initial postgresql superuser with password and database
159- # uses environment variables for input: POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_DB
165+ # create initial database
166+ # uses environment variables for input: POSTGRES_DB
160167docker_setup_db () {
161168 if [ " $POSTGRES_DB " != ' postgres' ]; then
162169 POSTGRES_DB= docker_process_sql --dbname postgres --set db=" $POSTGRES_DB " << -'EOSQL '
@@ -166,12 +173,20 @@ docker_setup_db() {
166173 fi
167174}
168175
169- # get user/pass and db from env vars or via file
176+ # Loads various settings that are used elsewhere in the script
177+ # This should be called before any other functions
170178docker_setup_env () {
171179 file_env ' POSTGRES_PASSWORD'
172180
173181 file_env ' POSTGRES_USER' ' postgres'
174182 file_env ' POSTGRES_DB' " $POSTGRES_USER "
183+ file_env ' POSTGRES_INITDB_ARGS'
184+
185+ declare -g DATABASE_ALREADY_EXISTS
186+ # look specifically for PG_VERSION, as it is expected in the DB dir
187+ if [ -s " $PGDATA /PG_VERSION" ]; then
188+ DATABASE_ALREADY_EXISTS=' true'
189+ fi
175190}
176191
177192# append md5 or trust auth to pg_hba.conf based on existence of POSTGRES_PASSWORD
@@ -189,10 +204,13 @@ pg_setup_hba_conf() {
189204 } >> " $PGDATA /pg_hba.conf"
190205}
191206
192- # start socket-only postgresql server for setting up user or running scripts
207+ # start socket-only postgresql server for setting up or running scripts
193208# all arguments will be passed along as arguments to `postgres` (via pg_ctl)
194209docker_temp_server_start () {
195- # internal start of server in order to allow set-up using psql-client
210+ if [ " $1 " = ' postgres' ]; then
211+ shift
212+ fi
213+ # internal start of server in order to allow setup using psql client
196214 # does not listen on external TCP/IP and waits until start finishes (can be overridden via args)
197215 PGUSER=" ${PGUSER:- $POSTGRES_USER } " \
198216 pg_ctl -D " $PGDATA " \
@@ -214,6 +232,7 @@ _main() {
214232
215233
216234 if [ " $1 " = ' postgres' ]; then
235+ docker_setup_env
217236 # setup data directories and permissions (when run as root)
218237 docker_create_db_directories
219238 if [ " $( id -u) " = ' 0' ]; then
@@ -222,22 +241,18 @@ _main() {
222241 fi
223242
224243 # only run initialization on an empty data directory
225- # look specifically for PG_VERSION, as it is expected in the DB dir
226- if [ ! -s " $PGDATA /PG_VERSION" ]; then
227- docker_init_database_dir
228-
229- docker_setup_env
244+ if [ -z " $DATABASE_ALREADY_EXISTS " ]; then
230245 docker_verify_minimum_env
246+ docker_init_database_dir
231247 pg_setup_hba_conf
232248
233249 # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless
234250 # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS
235251 export PGPASSWORD=" ${PGPASSWORD:- $POSTGRES_PASSWORD } "
236- docker_temp_server_start " ${ @: 2} "
252+ docker_temp_server_start " $@ "
237253
238254 docker_setup_db
239-
240- docker_process_init_files
255+ docker_process_init_files /docker-entrypoint-initdb.d/*
241256
242257 docker_temp_server_stop
243258 unset PGPASSWORD
0 commit comments