Skip to content

Commit 9c8ef03

Browse files
author
Jalexchen
authored
Revert "replace docker-entrypoint with latest (CircleCI-Public#69)" (CircleCI-Public#71)
This reverts commit 85c937f.
1 parent 85c937f commit 9c8ef03

File tree

3 files changed

+336
-7
lines changed

3 files changed

+336
-7
lines changed

Dockerfile.template

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22

33
# Do not edit individual Dockerfiles manually. Instead, please make changes to the Dockerfile.template, which will be used by the build script to generate Dockerfiles.
44

5-
# By policy, the base image tag should be a quarterly tag unless there's a
6-
# specific reason to use a different one. This means January, April, July, or
5+
# By policy, the base image tag should be a quarterly tag unless there's a
6+
# specific reason to use a different one. This means January, April, July, or
77
# October.
8-
9-
FROM cimg/%%PARENT%%:2023.01
8+
# Using November right now to include OpenSSL CVE fixes.
9+
FROM cimg/%%PARENT%%:2022.11
1010

1111
LABEL maintainer="Community & Partner Engineering Team <[email protected]>"
1212

@@ -84,8 +84,8 @@ RUN useradd postgres -m -s /bin/bash && \
8484

8585
ENV POSTGRES_DB=circle_test
8686

87-
RUN curl -sSL "http://raw.githubusercontent.com/docker-library/postgres/master/docker-entrypoint.sh" -o /usr/local/bin/docker-entrypoint.sh && \
88-
ln -s usr/local/bin/docker-entrypoint.sh / # backwards compat
87+
COPY docker-entrypoint.sh /usr/local/bin/
88+
RUN ln -s usr/local/bin/docker-entrypoint.sh / # backwards compat
8989

9090
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
9191
RUN mkdir -p /var/lib/postgresql && \

docker-entrypoint.sh

Lines changed: 329 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,329 @@
1+
#!/usr/bin/env bash
2+
set -Eeo pipefail
3+
# TODO swap to -Eeuo pipefail above (after handling all potentially-unset variables)
4+
5+
# usage: file_env VAR [DEFAULT]
6+
# ie: file_env 'XYZ_DB_PASSWORD' 'example'
7+
# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of
8+
# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature)
9+
file_env() {
10+
local var="$1"
11+
local fileVar="${var}_FILE"
12+
local def="${2:-}"
13+
if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then
14+
echo >&2 "error: both $var and $fileVar are set (but are exclusive)"
15+
exit 1
16+
fi
17+
local val="$def"
18+
if [ "${!var:-}" ]; then
19+
val="${!var}"
20+
elif [ "${!fileVar:-}" ]; then
21+
val="$(< "${!fileVar}")"
22+
fi
23+
export "$var"="$val"
24+
unset "$fileVar"
25+
}
26+
27+
# check to see if this file is being run or sourced from another script
28+
_is_sourced() {
29+
# https://unix.stackexchange.com/a/215279
30+
[ "${#FUNCNAME[@]}" -ge 2 ] \
31+
&& [ "${FUNCNAME[0]}" = '_is_sourced' ] \
32+
&& [ "${FUNCNAME[1]}" = 'source' ]
33+
}
34+
35+
# used to create initial postgres directories and if run as root, ensure ownership to the "postgres" user
36+
docker_create_db_directories() {
37+
local user; user="$(id -u)"
38+
39+
mkdir -p "$PGDATA"
40+
# ignore failure since there are cases where we can't chmod (and PostgreSQL might fail later anyhow - it's picky about permissions of this directory)
41+
chmod 700 "$PGDATA" || :
42+
43+
# ignore failure since it will be fine when using the image provided directory; see also https://github.com/docker-library/postgres/pull/289
44+
mkdir -p /var/run/postgresql || :
45+
chmod 775 /var/run/postgresql || :
46+
47+
# Create the transaction log directory before initdb is run so the directory is owned by the correct user
48+
if [ -n "$POSTGRES_INITDB_WALDIR" ]; then
49+
mkdir -p "$POSTGRES_INITDB_WALDIR"
50+
if [ "$user" = '0' ]; then
51+
find "$POSTGRES_INITDB_WALDIR" \! -user postgres -exec chown postgres '{}' +
52+
fi
53+
chmod 700 "$POSTGRES_INITDB_WALDIR"
54+
fi
55+
56+
# allow the container to be started with `--user`
57+
if [ "$user" = '0' ]; then
58+
find "$PGDATA" \! -user postgres -exec chown postgres '{}' +
59+
find /var/run/postgresql \! -user postgres -exec chown postgres '{}' +
60+
fi
61+
}
62+
63+
# initialize empty PGDATA directory with new database via 'initdb'
64+
# arguments to `initdb` can be passed via POSTGRES_INITDB_ARGS or as arguments to this function
65+
# `initdb` automatically creates the "postgres", "template0", and "template1" dbnames
66+
# this is also where the database user is created, specified by `POSTGRES_USER` env
67+
docker_init_database_dir() {
68+
# "initdb" is particular about the current user existing in "/etc/passwd", so we use "nss_wrapper" to fake that if necessary
69+
# see https://github.com/docker-library/postgres/pull/253, https://github.com/docker-library/postgres/issues/359, https://cwrap.org/nss_wrapper.html
70+
if ! getent passwd "$(id -u)" &> /dev/null && [ -e /usr/lib/libnss_wrapper.so ]; then
71+
export LD_PRELOAD='/usr/lib/libnss_wrapper.so'
72+
export NSS_WRAPPER_PASSWD="$(mktemp)"
73+
export NSS_WRAPPER_GROUP="$(mktemp)"
74+
echo "postgres:x:$(id -u):$(id -g):PostgreSQL:$PGDATA:/bin/false" > "$NSS_WRAPPER_PASSWD"
75+
echo "postgres:x:$(id -g):" > "$NSS_WRAPPER_GROUP"
76+
fi
77+
78+
if [ -n "$POSTGRES_INITDB_WALDIR" ]; then
79+
set -- --waldir "$POSTGRES_INITDB_WALDIR" "$@"
80+
fi
81+
82+
eval 'initdb --username="$POSTGRES_USER" --pwfile=<(echo "$POSTGRES_PASSWORD") '"$POSTGRES_INITDB_ARGS"' "$@"'
83+
84+
# unset/cleanup "nss_wrapper" bits
85+
if [ "${LD_PRELOAD:-}" = '/usr/lib/libnss_wrapper.so' ]; then
86+
rm -f "$NSS_WRAPPER_PASSWD" "$NSS_WRAPPER_GROUP"
87+
unset LD_PRELOAD NSS_WRAPPER_PASSWD NSS_WRAPPER_GROUP
88+
fi
89+
90+
echo "listen_addresses = '*'" >> "$PGDATA/postgresql.conf"
91+
}
92+
93+
# print large warning if POSTGRES_PASSWORD is long
94+
# error if both POSTGRES_PASSWORD is empty and POSTGRES_HOST_AUTH_METHOD is not 'trust'
95+
# print large warning if POSTGRES_HOST_AUTH_METHOD is set to 'trust'
96+
# assumes database is not set up, ie: [ -z "$DATABASE_ALREADY_EXISTS" ]
97+
docker_verify_minimum_env() {
98+
# check password first so we can output the warning before postgres
99+
# messes it up
100+
if [ "${#POSTGRES_PASSWORD}" -ge 100 ]; then
101+
cat >&2 <<-'EOWARN'
102+
103+
WARNING: The supplied POSTGRES_PASSWORD is 100+ characters.
104+
105+
This will not work if used via PGPASSWORD with "psql".
106+
107+
https://www.postgresql.org/message-id/flat/E1Rqxp2-0004Qt-PL%40wrigleys.postgresql.org (BUG #6412)
108+
https://github.com/docker-library/postgres/issues/507
109+
110+
EOWARN
111+
fi
112+
if [ -z "$POSTGRES_PASSWORD" ] && [ 'trust' != "$POSTGRES_HOST_AUTH_METHOD" ]; then
113+
# The - option suppresses leading tabs but *not* spaces. :)
114+
cat >&2 <<-'EOE'
115+
Error: Database is uninitialized and superuser password is not specified.
116+
You must specify POSTGRES_PASSWORD to a non-empty value for the
117+
superuser. For example, "-e POSTGRES_PASSWORD=password" on "docker run".
118+
119+
You may also use "POSTGRES_HOST_AUTH_METHOD=trust" to allow all
120+
connections without a password. This is *not* recommended.
121+
122+
See PostgreSQL documentation about "trust":
123+
https://www.postgresql.org/docs/current/auth-trust.html
124+
EOE
125+
exit 1
126+
fi
127+
if [ 'trust' = "$POSTGRES_HOST_AUTH_METHOD" ]; then
128+
cat >&2 <<-'EOWARN'
129+
********************************************************************************
130+
WARNING: POSTGRES_HOST_AUTH_METHOD has been set to "trust". This will allow
131+
anyone with access to the Postgres port to access your database without
132+
a password, even if POSTGRES_PASSWORD is set. See PostgreSQL
133+
documentation about "trust":
134+
https://www.postgresql.org/docs/current/auth-trust.html
135+
In Docker's default configuration, this is effectively any other
136+
container on the same system.
137+
138+
It is not recommended to use POSTGRES_HOST_AUTH_METHOD=trust. Replace
139+
it with "-e POSTGRES_PASSWORD=password" instead to set a password in
140+
"docker run".
141+
********************************************************************************
142+
EOWARN
143+
fi
144+
}
145+
146+
# usage: docker_process_init_files [file [file [...]]]
147+
# ie: docker_process_init_files /always-initdb.d/*
148+
# process initializer files, based on file extensions and permissions
149+
docker_process_init_files() {
150+
# psql here for backwards compatibility "${psql[@]}"
151+
psql=( docker_process_sql )
152+
153+
echo
154+
local f
155+
for f; do
156+
case "$f" in
157+
*.sh)
158+
# https://github.com/docker-library/postgres/issues/450#issuecomment-393167936
159+
# https://github.com/docker-library/postgres/pull/452
160+
if [ -x "$f" ]; then
161+
echo "$0: running $f"
162+
"$f"
163+
else
164+
echo "$0: sourcing $f"
165+
. "$f"
166+
fi
167+
;;
168+
*.sql) echo "$0: running $f"; docker_process_sql -f "$f"; echo ;;
169+
*.sql.gz) echo "$0: running $f"; gunzip -c "$f" | docker_process_sql; echo ;;
170+
*.sql.xz) echo "$0: running $f"; xzcat "$f" | docker_process_sql; echo ;;
171+
*) echo "$0: ignoring $f" ;;
172+
esac
173+
echo
174+
done
175+
}
176+
177+
# Execute sql script, passed via stdin (or -f flag of pqsl)
178+
# usage: docker_process_sql [psql-cli-args]
179+
# ie: docker_process_sql --dbname=mydb <<<'INSERT ...'
180+
# ie: docker_process_sql -f my-file.sql
181+
# ie: docker_process_sql <my-file.sql
182+
docker_process_sql() {
183+
local query_runner=( psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --no-password )
184+
if [ -n "$POSTGRES_DB" ]; then
185+
query_runner+=( --dbname "$POSTGRES_DB" )
186+
fi
187+
188+
PGHOST= PGHOSTADDR= "${query_runner[@]}" "$@"
189+
}
190+
191+
# create initial database
192+
# uses environment variables for input: POSTGRES_DB
193+
docker_setup_db() {
194+
local dbAlreadyExists
195+
dbAlreadyExists="$(
196+
POSTGRES_DB= docker_process_sql --dbname postgres --set db="$POSTGRES_DB" --tuples-only <<-'EOSQL'
197+
SELECT 1 FROM pg_database WHERE datname = :'db' ;
198+
EOSQL
199+
)"
200+
if [ -z "$dbAlreadyExists" ]; then
201+
POSTGRES_DB= docker_process_sql --dbname postgres --set db="$POSTGRES_DB" <<-'EOSQL'
202+
CREATE DATABASE :"db" ;
203+
EOSQL
204+
echo
205+
fi
206+
}
207+
208+
# Loads various settings that are used elsewhere in the script
209+
# This should be called before any other functions
210+
docker_setup_env() {
211+
file_env 'POSTGRES_PASSWORD'
212+
213+
file_env 'POSTGRES_USER' 'postgres'
214+
file_env 'POSTGRES_DB' "$POSTGRES_USER"
215+
file_env 'POSTGRES_INITDB_ARGS'
216+
# default authentication method is md5
217+
: "${POSTGRES_HOST_AUTH_METHOD:=md5}"
218+
219+
declare -g DATABASE_ALREADY_EXISTS
220+
# look specifically for PG_VERSION, as it is expected in the DB dir
221+
if [ -s "$PGDATA/PG_VERSION" ]; then
222+
DATABASE_ALREADY_EXISTS='true'
223+
fi
224+
}
225+
226+
# append POSTGRES_HOST_AUTH_METHOD to pg_hba.conf for "host" connections
227+
pg_setup_hba_conf() {
228+
{
229+
echo
230+
if [ 'trust' = "$POSTGRES_HOST_AUTH_METHOD" ]; then
231+
echo '# warning trust is enabled for all connections'
232+
echo '# see https://www.postgresql.org/docs/12/auth-trust.html'
233+
fi
234+
echo "host all all all $POSTGRES_HOST_AUTH_METHOD"
235+
} >> "$PGDATA/pg_hba.conf"
236+
}
237+
238+
# start socket-only postgresql server for setting up or running scripts
239+
# all arguments will be passed along as arguments to `postgres` (via pg_ctl)
240+
docker_temp_server_start() {
241+
if [ "$1" = 'postgres' ]; then
242+
shift
243+
fi
244+
245+
# internal start of server in order to allow setup using psql client
246+
# does not listen on external TCP/IP and waits until start finishes
247+
set -- "$@" -c listen_addresses='' -p "${PGPORT:-5432}"
248+
249+
PGUSER="${PGUSER:-$POSTGRES_USER}" \
250+
pg_ctl -D "$PGDATA" \
251+
-o "$(printf '%q ' "$@")" \
252+
-w start
253+
}
254+
255+
# stop postgresql server after done setting up user and running scripts
256+
docker_temp_server_stop() {
257+
PGUSER="${PGUSER:-postgres}" \
258+
pg_ctl -D "$PGDATA" -m fast -w stop
259+
}
260+
261+
# check arguments for an option that would cause postgres to stop
262+
# return true if there is one
263+
_pg_want_help() {
264+
local arg
265+
for arg; do
266+
case "$arg" in
267+
# postgres --help | grep 'then exit'
268+
# leaving out -C on purpose since it always fails and is unhelpful:
269+
# postgres: could not access the server configuration file "/var/lib/postgresql/data/postgresql.conf": No such file or directory
270+
-'?'|--help|--describe-config|-V|--version)
271+
return 0
272+
;;
273+
esac
274+
done
275+
return 1
276+
}
277+
278+
_main() {
279+
# if first arg looks like a flag, assume we want to run postgres server
280+
if [ "${1:0:1}" = '-' ]; then
281+
set -- postgres "$@"
282+
fi
283+
284+
if [ "$1" = 'postgres' ] && ! _pg_want_help "$@"; then
285+
docker_setup_env
286+
# setup data directories and permissions (when run as root)
287+
docker_create_db_directories
288+
if [ "$(id -u)" = '0' ]; then
289+
# then restart script as postgres user
290+
exec gosu postgres "$BASH_SOURCE" "$@"
291+
fi
292+
293+
# only run initialization on an empty data directory
294+
if [ -z "$DATABASE_ALREADY_EXISTS" ]; then
295+
docker_verify_minimum_env
296+
297+
# check dir permissions to reduce likelihood of half-initialized database
298+
ls /docker-entrypoint-initdb.d/ > /dev/null
299+
300+
docker_init_database_dir
301+
pg_setup_hba_conf
302+
303+
# PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless
304+
# e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS
305+
export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}"
306+
docker_temp_server_start "$@"
307+
308+
docker_setup_db
309+
docker_process_init_files /docker-entrypoint-initdb.d/*
310+
311+
docker_temp_server_stop
312+
unset PGPASSWORD
313+
314+
echo
315+
echo 'PostgreSQL init process complete; ready for start up.'
316+
echo
317+
else
318+
echo
319+
echo 'PostgreSQL Database directory appears to contain a database; Skipping initialization'
320+
echo
321+
fi
322+
fi
323+
324+
exec "$@"
325+
}
326+
327+
if ! _is_sourced; then
328+
_main "$@"
329+
fi

0 commit comments

Comments
 (0)