From b2ba9737317fb7dc1f1600903df3fec72127827e Mon Sep 17 00:00:00 2001 From: AnnatarHe Date: Sat, 24 Oct 2026 20:17:43 +0800 Subject: [PATCH] fix(image): name the role and database in the health check pg_isready defaulted to the OS user, so every probe connected as root to a database named root. It still reported healthy, but the server logged `FATAL: role "root" does not exist` every 10 s. The HEALTHCHECK now passes -U "${POSTGRES_USER:-postgres}" -d postgres in shell form, so the variable expands inside the container. test/smoke.sh runs the same line and fails if the server logged a missing role or database. Co-Authored-By: Claude Opus 5.5 --- AGENTS.md | 4 ++++ Dockerfile | 6 +++++- README.md | 7 +++++-- test/smoke.sh | 10 +++++++++- 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 6b49760..439e5e4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -60,6 +60,10 @@ test/smoke.sh # smoke-test any image, e.g. one pulled from GHCR - **The health check is TCP on purpose** (`pg_isready -h 127.0.0.1`). During first start the entrypoint runs a socket-only server, and the smoke test relies on the same distinction to wait for the real one. +- **The health check names its role and database** (`-U "${POSTGRES_USER:-postgres}" -d postgres`, + shell form so the variable expands in the container). Without them pg_isready connects as root, + still reports healthy, and the server logs `FATAL: role "root" does not exist` every 10 s. + `test/smoke.sh` runs the same line and fails on that FATAL, so change both together. - **Release pushes what was tested.** The release job builds with `load: true`, smoke-tests that image, then runs build-push again on the same builder, so every layer comes from that build's cache. Don't add a step between them that changes the build context. diff --git a/Dockerfile b/Dockerfile index 1d7337f..1861f30 100644 --- a/Dockerfile +++ b/Dockerfile @@ -56,5 +56,9 @@ COPY --chmod=755 scripts/update-extensions.sh /usr/local/bin/update-extensions.s # TCP on purpose: during first-start initialisation the entrypoint runs a # socket-only server, so this stays unhealthy until the real one is up. +# -U and -d because pg_isready otherwise connects as the OS user (root) to a +# database of the same name: it still reports healthy, but the server logs +# `FATAL: role "root" does not exist` on every probe. Shell form, so +# POSTGRES_USER expands inside the container. test/smoke.sh runs the same line. HEALTHCHECK --interval=10s --timeout=5s --start-period=60s --retries=5 \ - CMD ["pg_isready", "-q", "-h", "127.0.0.1"] + CMD pg_isready -q -h 127.0.0.1 -U "${POSTGRES_USER:-postgres}" -d postgres diff --git a/README.md b/README.md index cbdd521..f45a019 100644 --- a/README.md +++ b/README.md @@ -74,8 +74,11 @@ Restart=always WantedBy=multi-user.target ``` -The image ships a `HEALTHCHECK` (`pg_isready -h 127.0.0.1`). It turns healthy only once the real -server is listening on TCP, not while the first-start initialisation is still running. +The image ships a `HEALTHCHECK` +(`pg_isready -h 127.0.0.1 -U "${POSTGRES_USER:-postgres}" -d postgres`). It turns healthy only once +the real server is listening on TCP, not while the first-start initialisation is still running. It +names the role and database so that probes don't fill the server log with +`FATAL: role "root" does not exist`. Every variable and behaviour of the official `postgres` image applies unchanged, including `POSTGRES_USER`, `POSTGRES_INITDB_ARGS` and extra scripts in `/docker-entrypoint-initdb.d`. Name your diff --git a/test/smoke.sh b/test/smoke.sh index 4912955..582fcd4 100755 --- a/test/smoke.sh +++ b/test/smoke.sh @@ -49,7 +49,15 @@ if [ -z "${ready:-}" ]; then fi "${psql[@]}" -q <"$here/smoke.sql" -"$docker" exec "$name" pg_isready -q -h 127.0.0.1 +# The Dockerfile's HEALTHCHECK, verbatim. pg_isready exits 0 even when the +# server rejects its role, so also make sure the probe left no FATAL behind. +# The single quotes are deliberate: POSTGRES_USER expands in the container. +# shellcheck disable=SC2016 +"$docker" exec "$name" sh -c 'pg_isready -q -h 127.0.0.1 -U "${POSTGRES_USER:-postgres}" -d postgres' +if "$docker" logs "$name" 2>&1 | grep -E 'FATAL: +(role|database) .* does not exist'; then + echo "the health check makes the server log a FATAL on every probe" >&2 + exit 1 +fi "$docker" exec -u postgres "$name" update-extensions.sh versions="$("${psql[@]}" -qAt -F ' | ' <<'SQL'