-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdocker-entrypoint.sh
More file actions
355 lines (313 loc) · 14.8 KB
/
Copy pathdocker-entrypoint.sh
File metadata and controls
355 lines (313 loc) · 14.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
#!/usr/bin/env bash
set -Eeo pipefail
# ====== Postgres Pro 1C 16 ======
: "${PG_HOME:=/opt/pgpro/1c-16}"
: "${PGDATA:=/var/lib/pgpro/1c-16/data}"
export PATH="$PG_HOME/bin:$PATH"
: "${LANG:=ru_RU.UTF-8}"
: "${POSTGRES_LOCAL_AUTH_METHOD:=trust}"
: "${POSTGRES_HOST_AUTH_METHOD:=}"
: "${POSTGRES_HBA_ALLOW:=0.0.0.0/0 ::/0}"
: "${ALWAYS_INIT_DIR:=/docker-entrypoint-startup.d}"
file_env() {
local var="$1" fileVar="${var}_FILE" def="${2:-}"
if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then
printf >&2 'error: both %s and %s are set (but are exclusive)\n' "$var" "$fileVar"; exit 1
fi
local val="$def"
if [ "${!var:-}" ]; then val="${!var}"
elif [ "${!fileVar:-}" ]; then val="$(< "${!fileVar}")"; fi
export "$var"="$val"; unset "$fileVar"
}
_is_sourced() { [ "${#FUNCNAME[@]}" -ge 2 ] && [ "${FUNCNAME[0]}" = '_is_sourced' ] && [ "${FUNCNAME[1]}" = 'source' ]; }
docker_create_db_directories() {
local user; user="$(id -u)"
mkdir -p "$PGDATA" /var/run/postgresql
chmod 700 "$PGDATA" || :; chmod 3775 /var/run/postgresql || :
if [ -n "${POSTGRES_INITDB_WALDIR:-}" ]; then
mkdir -p "$POSTGRES_INITDB_WALDIR"
[ "$user" = '0' ] && find "$POSTGRES_INITDB_WALDIR" \! -user postgres -exec chown postgres '{}' +
chmod 700 "$POSTGRES_INITDB_WALDIR"
fi
if [ "$user" = '0' ]; then
find "$PGDATA" \! -user postgres -exec chown postgres '{}' +
find /var/run/postgresql \! -user postgres -exec chown postgres '{}' +
fi
}
ensure_superuser_password() {
[ -n "${POSTGRES_PASSWORD:-}" ] || { echo ">> skip password: POSTGRES_PASSWORD is empty"; return 0; }
local psql="$PG_HOME/bin/psql"
local user="${POSTGRES_USER:-postgres}"
if ! "$psql" -U postgres -d postgres -Atc "select 1 from pg_roles where rolname='${user}';" | grep -q 1; then
echo ">> role '${user}' does not exist, creating"
"$psql" -U postgres -d postgres -v ON_ERROR_STOP=1 -c "CREATE ROLE \"${user}\" SUPERUSER LOGIN;"
fi
echo ">> setting password for role '${user}'"
local enc="${POSTGRES_PASSWORD_ENCRYPTION:-}"
[ -n "$enc" ] && "$psql" -U postgres -d postgres -v ON_ERROR_STOP=1 -c "SET password_encryption = '${enc}';"
"$psql" -U postgres -d postgres -v ON_ERROR_STOP=1 -c "ALTER ROLE \"${user}\" WITH LOGIN PASSWORD \$\$${POSTGRES_PASSWORD}\$\$;"
}
ensure_listen_addresses() {
if grep -qE '^\s*listen_addresses\s*=' "$PGDATA/postgresql.conf" 2>/dev/null; then
sed -ri "s#^\s*listen_addresses\s*=.*#listen_addresses = '*'#" "$PGDATA/postgresql.conf"
else
echo "listen_addresses = '*'" >> "$PGDATA/postgresql.conf"
fi
}
ensure_logging_to_stdout() {
if grep -qE '^\s*logging_collector\s*=' "$PGDATA/postgresql.conf" 2>/dev/null; then
sed -ri "s#^\s*logging_collector\s*=.*#logging_collector = off#" "$PGDATA/postgresql.conf"
else
echo "logging_collector = off" >> "$PGDATA/postgresql.conf"
fi
if grep -qE '^\s*log_destination\s*=' "$PGDATA/postgresql.conf" 2>/dev/null; then
sed -ri "s#^\s*log_destination\s*=.*#log_destination = 'stderr'#" "$PGDATA/postgresql.conf"
else
echo "log_destination = 'stderr'" >> "$PGDATA/postgresql.conf"
fi
}
inject_local_trust_rules() {
local hba="$PGDATA/pg_hba.conf"
[ -f "$hba" ] || return 0
local tmp; tmp="$(mktemp "${hba}.XXXX")"
{
echo "# >>> injected by entrypoint: passwordless local/loopback access <<<"
echo "local all all trust"
echo "local replication all trust"
echo "host all all 127.0.0.1/32 trust"
echo "host all all ::1/128 trust"
echo "# <<< end injected <<<"
cat "$hba"
} > "$tmp"
mv "$tmp" "$hba"
}
pg_setup_hba_conf() {
local enc; enc="$("$PG_HOME/bin/postgres" -C password_encryption 2>/dev/null || true)"
: "${POSTGRES_HOST_AUTH_METHOD:=${enc:-scram-sha-256}}"
inject_local_trust_rules
if grep -qE '^local\s+all\s+all\s+\S+' "$PGDATA/pg_hba.conf" 2>/dev/null; then
sed -ri "s/^local\s+all\s+all\s+\S+/local all all ${POSTGRES_LOCAL_AUTH_METHOD}/" "$PGDATA/pg_hba.conf"
else
echo "local all all ${POSTGRES_LOCAL_AUTH_METHOD}" >> "$PGDATA/pg_hba.conf"
fi
if grep -qE '^local\s+replication\s+all\s+\S+' "$PGDATA/pg_hba.conf" 2>/dev/null; then
sed -ri "s/^local\s+replication\s+all\s+\S+/local replication all ${POSTGRES_LOCAL_AUTH_METHOD}/" "$PGDATA/pg_hba.conf"
fi
for cidr in ${POSTGRES_HBA_ALLOW}; do
cidr_esc="${cidr//\//\\/}"
if grep -qE "^host\s+all\s+all\s+${cidr_esc}\s+" "$PGDATA/pg_hba.conf" 2>/dev/null; then
sed -ri "s#^(host\s+all\s+all\s+${cidr_esc}\s+)\S+#\1${POSTGRES_HOST_AUTH_METHOD}#" "$PGDATA/pg_hba.conf"
else
printf 'host all all %-21s %s\n' "$cidr" "$POSTGRES_HOST_AUTH_METHOD" >> "$PGDATA/pg_hba.conf"
fi
done
}
docker_init_database_dir() {
local uid; uid="$(id -u)"
if ! getent passwd "$uid" &> /dev/null; then
for wrapper in {/usr,}/lib{/*,}/libnss_wrapper.so; do
[ -s "$wrapper" ] || continue
NSS_WRAPPER_PASSWD="$(mktemp)"; NSS_WRAPPER_GROUP="$(mktemp)"
export LD_PRELOAD="$wrapper" NSS_WRAPPER_PASSWD NSS_WRAPPER_GROUP
local gid; gid="$(id -g)"
printf 'postgres:x:%s:%s:PostgreSQL:%s:/bin/false\n' "$uid" "$gid" "$PGDATA" > "$NSS_WRAPPER_PASSWD"
printf 'postgres:x:%s:\n' "$gid" > "$NSS_WRAPPER_GROUP"
break
done
fi
[ -n "${POSTGRES_INITDB_WALDIR:-}" ] && set -- --waldir "$POSTGRES_INITDB_WALDIR" "$@"
eval '"$PG_HOME/bin/initdb" --username="$POSTGRES_USER" --pwfile=<(printf "%s\n" "$POSTGRES_PASSWORD") --encoding=UTF8 --locale="$LANG" ${POSTGRES_INITDB_ARGS:-} "$@"'
if [[ "${LD_PRELOAD:-}" == */libnss_wrapper.so ]]; then
rm -f "$NSS_WRAPPER_PASSWD" "$NSS_WRAPPER_GROUP"; unset LD_PRELOAD NSS_WRAPPER_PASSWD NSS_WRAPPER_GROUP
fi
ensure_listen_addresses
ensure_logging_to_stdout
}
docker_process_sql() {
local q=( "$PG_HOME/bin/psql" -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --no-password --no-psqlrc )
[ -n "$POSTGRES_DB" ] && q+=( --dbname "$POSTGRES_DB" )
PGHOST= PGHOSTADDR= "${q[@]}" "$@"
}
docker_process_init_files() {
printf '\n'; local f
for f; do
case "$f" in
*.sh) if [ -x "$f" ]; then echo "$0: running $f"; "$f"; else echo "$0: sourcing $f"; . "$f"; fi ;;
*.sql) echo "$0: running $f"; docker_process_sql -f "$f"; echo ;;
*.sql.gz) echo "$0: running $f"; gunzip -c "$f" | docker_process_sql; echo ;;
*.sql.xz) echo "$0: running $f"; xzcat "$f" | docker_process_sql; echo ;;
*.sql.zst) echo "$0: running $f"; zstd -dc "$f" | docker_process_sql; echo ;;
*) echo "$0: ignoring $f" ;;
esac
printf '\n'
done
}
docker_setup_db() {
local dbExists
dbExists="$(
POSTGRES_DB= docker_process_sql --dbname postgres --set db="$POSTGRES_DB" --tuples-only <<-'EOSQL'
SELECT 1 FROM pg_database WHERE datname = :'db' ;
EOSQL
)"
if [ -z "$dbExists" ]; then
POSTGRES_DB= docker_process_sql --dbname postgres --set db="$POSTGRES_DB" <<-'EOSQL'
CREATE DATABASE :"db" ;
EOSQL
printf '\n'
fi
}
start_temp_server_once() {
local hba_override="${1:-}"
local opts="-c listen_addresses=''"
[ -n "$hba_override" ] && opts="$opts -c hba_file=${hba_override}"
NOTIFY_SOCKET= PGUSER="${PGUSER:-$POSTGRES_USER}" \
"$PG_HOME/bin/pg_ctl" -D "$PGDATA" -o "$opts" -w start
}
stop_temp_server() {
PGUSER="${PGUSER:-postgres}" "$PG_HOME/bin/pg_ctl" -D "$PGDATA" -m fast -w stop
}
password_is_valid() {
[ -z "${POSTGRES_PASSWORD:-}" ] && return 1
PGPASSWORD="$POSTGRES_PASSWORD" "$PG_HOME/bin/psql" -U postgres -d postgres -v ON_ERROR_STOP=1 -Atc "SELECT 1" >/dev/null 2>&1
}
# --- fasttrun/fastrun ---
ensure_fastrun_for_1c() {
local ext
if "$PG_HOME/bin/psql" -U postgres -d postgres -Atc "select 1 from pg_available_extensions where name='fasttrun';" | grep -q 1; then
ext="fasttrun"
elif "$PG_HOME/bin/psql" -U postgres -d postgres -Atc "select 1 from pg_available_extensions where name='fastrun';" | grep -q 1; then
ext="fastrun"
else
echo ">> fasttrun/fastrun not available"; return 0
fi
echo ">> ensuring ${ext}…"
"$PG_HOME/bin/psql" -U postgres -d template1 -v ON_ERROR_STOP=1 -c "CREATE EXTENSION IF NOT EXISTS ${ext} SCHEMA public;"
"$PG_HOME/bin/psql" -U postgres -d postgres -v ON_ERROR_STOP=1 -c "CREATE EXTENSION IF NOT EXISTS ${ext} SCHEMA public;"
local allow="$("$PG_HOME/bin/psql" -U postgres -d postgres -Atc "SELECT datallowconn FROM pg_database WHERE datname='template0';")"
[ "$allow" = "t" ] || "$PG_HOME/bin/psql" -U postgres -d postgres -c "UPDATE pg_database SET datallowconn=TRUE WHERE datname='template0';"
"$PG_HOME/bin/psql" -U postgres -d template0 -v ON_ERROR_STOP=1 -c "CREATE EXTENSION IF NOT EXISTS ${ext} SCHEMA public;"
[ "$allow" = "t" ] || "$PG_HOME/bin/psql" -U postgres -d postgres -c "UPDATE pg_database SET datallowconn=FALSE WHERE datname='template0';"
}
# --- fulleq ---
ensure_fulleq_for_1c() {
if ! "$PG_HOME/bin/psql" -U postgres -d postgres -Atc \
"SELECT 1 FROM pg_available_extensions WHERE name='fulleq';" | grep -q 1; then
echo ">> fulleq extension is not available (no control/lib). Install *-contrib for your line."
return 0
fi
echo ">> ensuring fulleq…"
"$PG_HOME/bin/psql" -U postgres -d template1 -v ON_ERROR_STOP=1 -c "CREATE EXTENSION IF NOT EXISTS fulleq WITH SCHEMA public;"
"$PG_HOME/bin/psql" -U postgres -d postgres -v ON_ERROR_STOP=1 -c "CREATE EXTENSION IF NOT EXISTS fulleq WITH SCHEMA public;"
local allow
allow="$("$PG_HOME/bin/psql" -U postgres -d postgres -Atc "SELECT datallowconn FROM pg_database WHERE datname='template0';")"
[ "$allow" = "t" ] || "$PG_HOME/bin/psql" -U postgres -d postgres -v ON_ERROR_STOP=1 -c "UPDATE pg_database SET datallowconn=TRUE WHERE datname='template0';"
"$PG_HOME/bin/psql" -U postgres -d template0 -v ON_ERROR_STOP=1 -c "CREATE EXTENSION IF NOT EXISTS fulleq WITH SCHEMA public;"
[ "$allow" = "t" ] || "$PG_HOME/bin/psql" -U postgres -d postgres -v ON_ERROR_STOP=1 -c "UPDATE pg_database SET datallowconn=FALSE WHERE datname='template0';"
}
# --- binrowver() ---
ensure_binrowver_for_1c() {
echo ">> ensuring binrowver()…"
_create_in_db() {
local db="$1"
"$PG_HOME/bin/psql" -U postgres -d "$db" -Atc \
"SELECT 1 FROM pg_proc WHERE proname='binrowver' AND pg_function_is_visible(oid);" | grep -q 1 && return 0
"$PG_HOME/bin/psql" -U postgres -d "$db" -v ON_ERROR_STOP=1 <<'SQL'
CREATE OR REPLACE FUNCTION public.binrowver(p1 int4)
RETURNS bytea
LANGUAGE plpgsql
IMMUTABLE
STRICT
AS $$
DECLARE
b bytea := E'\\000\\000\\000\\000\\000\\000\\000\\000'::bytea;
BEGIN
b := set_byte(b, 4, (p1 / 16777216) % 256);
b := set_byte(b, 5, (p1 / 65536) % 256);
b := set_byte(b, 6, (p1 / 256) % 256);
b := set_byte(b, 7, (p1 ) % 256);
RETURN b;
END $$;
SQL
}
_create_in_db template1
_create_in_db postgres
local allow; allow="$("$PG_HOME/bin/psql" -U postgres -d postgres -Atc "SELECT datallowconn FROM pg_database WHERE datname='template0';")"
[ "$allow" = "t" ] || "$PG_HOME/bin/psql" -U postgres -d postgres -c "UPDATE pg_database SET datallowconn=TRUE WHERE datname='template0';"
_create_in_db template0
[ "$allow" = "t" ] || "$PG_HOME/bin/psql" -U postgres -d postgres -c "UPDATE pg_database SET datallowconn=FALSE WHERE datname='template0';"
}
# --- mchar/mvarchar ---
ensure_mchar_for_1c() {
if ! "$PG_HOME/bin/psql" -U postgres -d postgres -Atc "SELECT 1 FROM pg_available_extensions WHERE name='mchar';" | grep -q 1; then
echo ">> mchar extension is not available; check package postgrespro-1c-16"; return 0
fi
echo ">> ensuring mchar…"
if ! "$PG_HOME/bin/psql" -U postgres -d template1 -Atc "SELECT 1 FROM pg_type WHERE typname='mchar' AND typnamespace='pg_catalog'::regnamespace;" | grep -q 1; then
"$PG_HOME/bin/psql" -U postgres -d template1 -v ON_ERROR_STOP=1 -c "CREATE EXTENSION IF NOT EXISTS mchar WITH SCHEMA pg_catalog;"
fi
if ! "$PG_HOME/bin/psql" -U postgres -d postgres -Atc "SELECT 1 FROM pg_type WHERE typname='mchar' AND typnamespace='pg_catalog'::regnamespace;" | grep -q 1; then
"$PG_HOME/bin/psql" -U postgres -d postgres -v ON_ERROR_STOP=1 -c "CREATE EXTENSION IF NOT EXISTS mchar WITH SCHEMA pg_catalog;"
fi
local allow
allow="$("$PG_HOME/bin/psql" -U postgres -d postgres -Atc "SELECT datallowconn FROM pg_database WHERE datname='template0';")"
if [ "$allow" != "t" ]; then
"$PG_HOME/bin/psql" -U postgres -d postgres -v ON_ERROR_STOP=1 -c "UPDATE pg_database SET datallowconn = TRUE WHERE datname = 'template0';"
fi
if ! "$PG_HOME/bin/psql" -U postgres -d template0 -Atc "SELECT 1 FROM pg_type WHERE typname='mchar' AND typnamespace='pg_catalog'::regnamespace;" | grep -q 1; then
"$PG_HOME/bin/psql" -U postgres -d template0 -v ON_ERROR_STOP=1 -c "CREATE EXTENSION IF NOT EXISTS mchar WITH SCHEMA pg_catalog;"
fi
if [ "$allow" != "t" ]; then
"$PG_HOME/bin/psql" -U postgres -d postgres -v ON_ERROR_STOP=1 -c "UPDATE pg_database SET datallowconn = FALSE WHERE datname = 'template0';"
fi
echo ">> mchar ensured in template0, template1 and postgres"
}
_pg_want_help() {
local arg; for arg; do case "$arg" in -'?'|--help|--describe-config|-V|--version) return 0 ;; esac; done
return 1
}
_main() {
if [ "${1:0:1}" = '-' ]; then set -- postgres "$@"; fi
if [ "$1" = 'postgres' ] && ! _pg_want_help "$@"; then
file_env 'POSTGRES_PASSWORD'
file_env 'POSTGRES_USER' 'postgres'
file_env 'POSTGRES_DB' "$POSTGRES_USER"
file_env 'POSTGRES_INITDB_ARGS'
: "${POSTGRES_HOST_AUTH_METHOD:=}"
docker_create_db_directories
if [ "$(id -u)" = '0' ]; then exec gosu postgres "$BASH_SOURCE" "$@"; fi
if [ ! -s "$PGDATA/PG_VERSION" ]; then
docker_init_database_dir
pg_setup_hba_conf "$@"
export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}"
start_temp_server_once
ensure_superuser_password
ensure_mchar_for_1c
ensure_fastrun_for_1c
ensure_fulleq_for_1c
ensure_binrowver_for_1c
docker_setup_db
docker_process_init_files /docker-entrypoint-initdb.d/* 2>/dev/null || true
stop_temp_server
unset PGPASSWORD
echo; echo "PostgreSQL init process complete; ready for start up."; echo
else
# existing database cluster
ensure_listen_addresses
ensure_logging_to_stdout
pg_setup_hba_conf "$@"
start_temp_server_once
ensure_superuser_password
ensure_mchar_for_1c
ensure_fastrun_for_1c
ensure_fulleq_for_1c
ensure_binrowver_for_1c
if [ -d "$ALWAYS_INIT_DIR" ] && [ "$(ls -A "$ALWAYS_INIT_DIR" 2>/dev/null)" ]; then
docker_process_init_files "$ALWAYS_INIT_DIR"/* 2>/dev/null || true
fi
stop_temp_server
echo; echo "PostgreSQL data directory exists; skipping init."; echo
fi
fi
exec "$@"
}
if ! _is_sourced; then _main "$@"; fi