├── 13 ├── alpine3.21 │ ├── Dockerfile │ ├── docker-ensure-initdb.sh │ └── docker-entrypoint.sh ├── alpine3.22 │ ├── Dockerfile │ ├── docker-ensure-initdb.sh │ └── docker-entrypoint.sh ├── bookworm │ ├── Dockerfile │ ├── docker-ensure-initdb.sh │ └── docker-entrypoint.sh └── bullseye │ ├── Dockerfile │ ├── docker-ensure-initdb.sh │ └── docker-entrypoint.sh ├── 14 ├── alpine3.21 │ ├── Dockerfile │ ├── docker-ensure-initdb.sh │ └── docker-entrypoint.sh ├── alpine3.22 │ ├── Dockerfile │ ├── docker-ensure-initdb.sh │ └── docker-entrypoint.sh ├── bookworm │ ├── Dockerfile │ ├── docker-ensure-initdb.sh │ └── docker-entrypoint.sh └── bullseye │ ├── Dockerfile │ ├── docker-ensure-initdb.sh │ └── docker-entrypoint.sh ├── 15 ├── alpine3.21 │ ├── Dockerfile │ ├── docker-ensure-initdb.sh │ └── docker-entrypoint.sh ├── alpine3.22 │ ├── Dockerfile │ ├── docker-ensure-initdb.sh │ └── docker-entrypoint.sh ├── bookworm │ ├── Dockerfile │ ├── docker-ensure-initdb.sh │ └── docker-entrypoint.sh └── bullseye │ ├── Dockerfile │ ├── docker-ensure-initdb.sh │ └── docker-entrypoint.sh ├── 16 ├── alpine3.21 │ ├── Dockerfile │ ├── docker-ensure-initdb.sh │ └── docker-entrypoint.sh ├── alpine3.22 │ ├── Dockerfile │ ├── docker-ensure-initdb.sh │ └── docker-entrypoint.sh ├── bookworm │ ├── Dockerfile │ ├── docker-ensure-initdb.sh │ └── docker-entrypoint.sh └── bullseye │ ├── Dockerfile │ ├── docker-ensure-initdb.sh │ └── docker-entrypoint.sh ├── 17 ├── alpine3.21 │ ├── Dockerfile │ ├── docker-ensure-initdb.sh │ └── docker-entrypoint.sh ├── alpine3.22 │ ├── Dockerfile │ ├── docker-ensure-initdb.sh │ └── docker-entrypoint.sh ├── bookworm │ ├── Dockerfile │ ├── docker-ensure-initdb.sh │ └── docker-entrypoint.sh └── bullseye │ ├── Dockerfile │ ├── docker-ensure-initdb.sh │ └── docker-entrypoint.sh ├── .gitattributes ├── .github └── workflows │ ├── ci.yml │ ├── munge.sh │ └── verify-templating.yml ├── .gitignore ├── AUTHORS ├── Dockerfile-alpine.template ├── Dockerfile-debian.template ├── LICENSE ├── README.md ├── apply-templates.sh ├── docker-ensure-initdb.sh ├── docker-entrypoint.sh ├── generate-stackbrew-library.sh ├── update.sh ├── versions.json └── versions.sh /.gitattributes: -------------------------------------------------------------------------------- 1 | /*/**/Dockerfile linguist-generated 2 | /*/**/docker-ensure-initdb.sh linguist-generated 3 | /*/**/docker-entrypoint.sh linguist-generated 4 | /Dockerfile*.template linguist-language=Dockerfile 5 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: GitHub CI 2 | 3 | on: 4 | pull_request: 5 | push: 6 | schedule: 7 | - cron: 0 0 * * 0 8 | workflow_dispatch: 9 | 10 | defaults: 11 | run: 12 | shell: 'bash -Eeuo pipefail -x {0}' 13 | 14 | jobs: 15 | 16 | generate-jobs: 17 | name: Generate Jobs 18 | runs-on: ubuntu-latest 19 | outputs: 20 | strategy: ${{ steps.generate-jobs.outputs.strategy }} 21 | steps: 22 | - uses: actions/checkout@v4 23 | - uses: docker-library/bashbrew@HEAD 24 | - id: generate-jobs 25 | name: Generate Jobs 26 | run: | 27 | strategy="$("$BASHBREW_SCRIPTS/github-actions/generate.sh")" 28 | strategy="$(.github/workflows/munge.sh -c <<<"$strategy")" 29 | echo "strategy=$strategy" >> "$GITHUB_OUTPUT" 30 | jq . <<<"$strategy" # sanity check / debugging aid 31 | 32 | test: 33 | needs: generate-jobs 34 | strategy: ${{ fromJson(needs.generate-jobs.outputs.strategy) }} 35 | name: ${{ matrix.name }} 36 | runs-on: ${{ matrix.os }} 37 | steps: 38 | - uses: actions/checkout@v4 39 | - name: Prepare Environment 40 | run: ${{ matrix.runs.prepare }} 41 | - name: Pull Dependencies 42 | run: ${{ matrix.runs.pull }} 43 | - name: Build ${{ matrix.name }} 44 | run: ${{ matrix.runs.build }} 45 | - name: History ${{ matrix.name }} 46 | run: ${{ matrix.runs.history }} 47 | - name: Test ${{ matrix.name }} 48 | run: ${{ matrix.runs.test }} 49 | - name: '"docker images"' 50 | run: ${{ matrix.runs.images }} 51 | -------------------------------------------------------------------------------- /.github/workflows/munge.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | # copy all the Debian build jobs into "force deb build" jobs which build like architectures upstream doesn't publish for will 5 | jq \ 6 | --arg prefix '[ "$(dpkg --print-architecture)" = "amd64" ]' \ 7 | --arg dfMunge 'grep -qE "amd64 [|] " "$df"; sed -ri -e "s/amd64 [|] //g" "$df"; ! grep -qE "amd64 [|] " "$df"' \ 8 | ' 9 | .matrix.include += [ 10 | .matrix.include[] 11 | | select(.name | test(" (.+)") | not) # ignore any existing munged builds 12 | | select(.meta.froms[] | test("^debian:|^ubuntu:")) 13 | | .name += " (force deb build)" 14 | | .runs.build = ( 15 | [ 16 | "# force us to build debs instead of downloading them", 17 | $prefix, 18 | ("for df in " + ([ .meta.dockerfiles[] | @sh ] | join(" ")) + "; do " + $dfMunge + "; done"), 19 | .runs.build 20 | ] | join ("\n") 21 | ) 22 | ] 23 | ' "$@" 24 | -------------------------------------------------------------------------------- /.github/workflows/verify-templating.yml: -------------------------------------------------------------------------------- 1 | name: Verify Templating 2 | 3 | on: 4 | pull_request: 5 | push: 6 | workflow_dispatch: 7 | 8 | defaults: 9 | run: 10 | shell: 'bash -Eeuo pipefail -x {0}' 11 | 12 | jobs: 13 | apply-templates: 14 | name: Check For Uncomitted Changes 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v4 18 | - run: ./apply-templates.sh 19 | - run: git diff --exit-code 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .jq-template.awk 2 | -------------------------------------------------------------------------------- /13/alpine3.21/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" 3 | # 4 | # PLEASE DO NOT EDIT IT DIRECTLY. 5 | # 6 | 7 | FROM alpine:3.21 8 | 9 | # 70 is the standard uid/gid for "postgres" in Alpine 10 | # https://git.alpinelinux.org/aports/tree/main/postgresql-common/postgresql-common.pre-install?h=3.22-stable 11 | RUN set -eux; \ 12 | addgroup -g 70 -S postgres; \ 13 | adduser -u 70 -S -D -G postgres -H -h /var/lib/postgresql -s /bin/sh postgres; \ 14 | # also create the postgres user's home directory with appropriate permissions 15 | # see https://github.com/docker-library/postgres/issues/274 16 | install --verbose --directory --owner postgres --group postgres --mode 1777 /var/lib/postgresql 17 | 18 | # grab gosu for easy step-down from root 19 | # https://github.com/tianon/gosu/releases 20 | ENV GOSU_VERSION 1.17 21 | RUN set -eux; \ 22 | \ 23 | apk add --no-cache --virtual .gosu-deps \ 24 | ca-certificates \ 25 | dpkg \ 26 | gnupg \ 27 | ; \ 28 | \ 29 | dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \ 30 | wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \ 31 | wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \ 32 | \ 33 | # verify the signature 34 | export GNUPGHOME="$(mktemp -d)"; \ 35 | gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ 36 | gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \ 37 | gpgconf --kill all; \ 38 | rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \ 39 | \ 40 | # clean up fetch dependencies 41 | apk del --no-network .gosu-deps; \ 42 | \ 43 | chmod +x /usr/local/bin/gosu; \ 44 | # verify that the binary works 45 | gosu --version; \ 46 | gosu nobody true 47 | RUN set -eux; ln -svf gosu /usr/local/bin/su-exec; su-exec nobody true # backwards compatibility (removed in PostgreSQL 17+) 48 | 49 | # make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default 50 | # alpine doesn't require explicit locale-file generation 51 | ENV LANG en_US.utf8 52 | 53 | RUN mkdir /docker-entrypoint-initdb.d 54 | 55 | ENV PG_MAJOR 13 56 | ENV PG_VERSION 13.21 57 | ENV PG_SHA256 dcda1294df45f033b0656cf7a8e4afbbc624c25e1b144aec79530f74d7ef4ab4 58 | 59 | ENV DOCKER_PG_LLVM_DEPS \ 60 | llvm19-dev \ 61 | clang19 62 | 63 | RUN set -eux; \ 64 | \ 65 | wget -O postgresql.tar.bz2 "https://ftp.postgresql.org/pub/source/v$PG_VERSION/postgresql-$PG_VERSION.tar.bz2"; \ 66 | echo "$PG_SHA256 *postgresql.tar.bz2" | sha256sum -c -; \ 67 | mkdir -p /usr/src/postgresql; \ 68 | tar \ 69 | --extract \ 70 | --file postgresql.tar.bz2 \ 71 | --directory /usr/src/postgresql \ 72 | --strip-components 1 \ 73 | ; \ 74 | rm postgresql.tar.bz2; \ 75 | \ 76 | apk add --no-cache --virtual .build-deps \ 77 | $DOCKER_PG_LLVM_DEPS \ 78 | bison \ 79 | coreutils \ 80 | dpkg-dev dpkg \ 81 | flex \ 82 | g++ \ 83 | gcc \ 84 | krb5-dev \ 85 | libc-dev \ 86 | libedit-dev \ 87 | libxml2-dev \ 88 | libxslt-dev \ 89 | linux-headers \ 90 | make \ 91 | openldap-dev \ 92 | openssl-dev \ 93 | perl-dev \ 94 | perl-ipc-run \ 95 | perl-utils \ 96 | python3-dev \ 97 | tcl-dev \ 98 | util-linux-dev \ 99 | zlib-dev \ 100 | # https://www.postgresql.org/docs/10/static/release-10.html#id-1.11.6.9.5.13 101 | icu-dev \ 102 | ; \ 103 | \ 104 | cd /usr/src/postgresql; \ 105 | # update "DEFAULT_PGSOCKET_DIR" to "/var/run/postgresql" (matching Debian) 106 | # see https://anonscm.debian.org/git/pkg-postgresql/postgresql.git/tree/debian/patches/51-default-sockets-in-var.patch?id=8b539fcb3e093a521c095e70bdfa76887217b89f 107 | awk '$1 == "#define" && $2 == "DEFAULT_PGSOCKET_DIR" && $3 == "\"/tmp\"" { $3 = "\"/var/run/postgresql\""; print; next } { print }' src/include/pg_config_manual.h > src/include/pg_config_manual.h.new; \ 108 | grep '/var/run/postgresql' src/include/pg_config_manual.h.new; \ 109 | mv src/include/pg_config_manual.h.new src/include/pg_config_manual.h; \ 110 | gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \ 111 | \ 112 | # https://git.alpinelinux.org/aports/tree/community/postgresql15/APKBUILD?h=3.22-stable#n176 ("export LLVM_CONFIG") 113 | export LLVM_CONFIG="/usr/lib/llvm19/bin/llvm-config"; \ 114 | # https://git.alpinelinux.org/aports/tree/community/postgresql15/APKBUILD?h=3.22-stable#n180 ("older clang versions don't have a 'clang' exe anymore.") 115 | export CLANG=clang-19; \ 116 | \ 117 | # configure options taken from: 118 | # https://anonscm.debian.org/cgit/pkg-postgresql/postgresql.git/tree/debian/rules?h=9.5 119 | ./configure \ 120 | --enable-option-checking=fatal \ 121 | --build="$gnuArch" \ 122 | # "/usr/src/postgresql/src/backend/access/common/tupconvert.c:105: undefined reference to `libintl_gettext'" 123 | # --enable-nls \ 124 | --enable-integer-datetimes \ 125 | --enable-thread-safety \ 126 | --enable-tap-tests \ 127 | # skip debugging info -- we want tiny size instead 128 | # --enable-debug \ 129 | --disable-rpath \ 130 | --with-uuid=e2fs \ 131 | --with-gnu-ld \ 132 | --with-pgport=5432 \ 133 | --with-system-tzdata=/usr/share/zoneinfo \ 134 | --prefix=/usr/local \ 135 | --with-includes=/usr/local/include \ 136 | --with-libraries=/usr/local/lib \ 137 | --with-gssapi \ 138 | --with-ldap \ 139 | --with-tcl \ 140 | --with-perl \ 141 | --with-python \ 142 | # --with-pam \ 143 | --with-openssl \ 144 | --with-libxml \ 145 | --with-libxslt \ 146 | --with-icu \ 147 | --with-llvm \ 148 | ; \ 149 | make -j "$(nproc)" world-bin; \ 150 | make install-world-bin; \ 151 | make -C contrib install; \ 152 | \ 153 | runDeps="$( \ 154 | scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \ 155 | | tr ',' '\n' \ 156 | | sort -u \ 157 | | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ 158 | # Remove plperl, plpython and pltcl dependencies by default to save image size 159 | # To use the pl extensions, those have to be installed in a derived image 160 | | grep -v -e perl -e python -e tcl \ 161 | )"; \ 162 | apk add --no-cache --virtual .postgresql-rundeps \ 163 | $runDeps \ 164 | bash \ 165 | tzdata \ 166 | zstd \ 167 | # https://wiki.alpinelinux.org/wiki/Release_Notes_for_Alpine_3.16.0#ICU_data_split 168 | icu-data-full \ 169 | # https://git.alpinelinux.org/aports/tree/community/nss_wrapper/APKBUILD?h=3.22-stable#n7 ("ppc64le: test case segfaults") 170 | $([ "$(apk --print-arch)" != 'ppc64le' ] && echo 'nss_wrapper') \ 171 | ; \ 172 | apk del --no-network .build-deps; \ 173 | cd /; \ 174 | rm -rf \ 175 | /usr/src/postgresql \ 176 | /usr/local/share/doc \ 177 | /usr/local/share/man \ 178 | ; \ 179 | \ 180 | postgres --version 181 | 182 | # make the sample config easier to munge (and "correct by default") 183 | RUN set -eux; \ 184 | cp -v /usr/local/share/postgresql/postgresql.conf.sample /usr/local/share/postgresql/postgresql.conf.sample.orig; \ 185 | sed -ri "s!^#?(listen_addresses)\s*=\s*\S+.*!\1 = '*'!" /usr/local/share/postgresql/postgresql.conf.sample; \ 186 | grep -F "listen_addresses = '*'" /usr/local/share/postgresql/postgresql.conf.sample 187 | 188 | RUN install --verbose --directory --owner postgres --group postgres --mode 3777 /var/run/postgresql 189 | 190 | ENV PGDATA /var/lib/postgresql/data 191 | # this 1777 will be replaced by 0700 at runtime (allows semi-arbitrary "--user" values) 192 | RUN install --verbose --directory --owner postgres --group postgres --mode 1777 "$PGDATA" 193 | VOLUME /var/lib/postgresql/data 194 | 195 | COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ 196 | RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh 197 | ENTRYPOINT ["docker-entrypoint.sh"] 198 | 199 | # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL 200 | # calls "Fast Shutdown mode" wherein new connections are disallowed and any 201 | # in-progress transactions are aborted, allowing PostgreSQL to stop cleanly and 202 | # flush tables to disk. 203 | # 204 | # See https://www.postgresql.org/docs/current/server-shutdown.html for more details 205 | # about available PostgreSQL server shutdown signals. 206 | # 207 | # See also https://www.postgresql.org/docs/current/server-start.html for further 208 | # justification of this as the default value, namely that the example (and 209 | # shipped) systemd service files use the "Fast Shutdown mode" for service 210 | # termination. 211 | # 212 | STOPSIGNAL SIGINT 213 | # 214 | # An additional setting that is recommended for all users regardless of this 215 | # value is the runtime "--stop-timeout" (or your orchestrator/runtime's 216 | # equivalent) for controlling how long to wait between sending the defined 217 | # STOPSIGNAL and sending SIGKILL. 218 | # 219 | # The default in most runtimes (such as Docker) is 10 seconds, and the 220 | # documentation at https://www.postgresql.org/docs/current/server-start.html notes 221 | # that even 90 seconds may not be long enough in many instances. 222 | 223 | EXPOSE 5432 224 | CMD ["postgres"] 225 | -------------------------------------------------------------------------------- /13/alpine3.21/docker-ensure-initdb.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | # 5 | # This script is intended for three main use cases: 6 | # 7 | # 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior 8 | # 9 | # 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution 10 | # (no-op if database is already initialized) 11 | # 12 | # 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use 13 | # (error if database is already initialized) 14 | # 15 | 16 | source /usr/local/bin/docker-entrypoint.sh 17 | 18 | # arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) 19 | if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then 20 | set -- postgres "$@" 21 | fi 22 | 23 | # see also "_main" in "docker-entrypoint.sh" 24 | 25 | docker_setup_env 26 | # setup data directories and permissions (when run as root) 27 | docker_create_db_directories 28 | if [ "$(id -u)" = '0' ]; then 29 | # then restart script as postgres user 30 | exec gosu postgres "$BASH_SOURCE" "$@" 31 | fi 32 | 33 | # only run initialization on an empty data directory 34 | if [ -z "$DATABASE_ALREADY_EXISTS" ]; then 35 | docker_verify_minimum_env 36 | 37 | # check dir permissions to reduce likelihood of half-initialized database 38 | ls /docker-entrypoint-initdb.d/ > /dev/null 39 | 40 | docker_init_database_dir 41 | pg_setup_hba_conf "$@" 42 | 43 | # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless 44 | # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS 45 | export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" 46 | docker_temp_server_start "$@" 47 | 48 | docker_setup_db 49 | docker_process_init_files /docker-entrypoint-initdb.d/* 50 | 51 | docker_temp_server_stop 52 | unset PGPASSWORD 53 | else 54 | self="$(basename "$0")" 55 | case "$self" in 56 | docker-ensure-initdb.sh) 57 | echo >&2 "$self: note: database already initialized in '$PGDATA'!" 58 | exit 0 59 | ;; 60 | 61 | docker-enforce-initdb.sh) 62 | echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" 63 | exit 1 64 | ;; 65 | 66 | *) 67 | echo >&2 "$self: error: unknown file name: $self" 68 | exit 99 69 | ;; 70 | esac 71 | fi 72 | -------------------------------------------------------------------------------- /13/alpine3.22/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" 3 | # 4 | # PLEASE DO NOT EDIT IT DIRECTLY. 5 | # 6 | 7 | FROM alpine:3.22 8 | 9 | # 70 is the standard uid/gid for "postgres" in Alpine 10 | # https://git.alpinelinux.org/aports/tree/main/postgresql-common/postgresql-common.pre-install?h=3.22-stable 11 | RUN set -eux; \ 12 | addgroup -g 70 -S postgres; \ 13 | adduser -u 70 -S -D -G postgres -H -h /var/lib/postgresql -s /bin/sh postgres; \ 14 | # also create the postgres user's home directory with appropriate permissions 15 | # see https://github.com/docker-library/postgres/issues/274 16 | install --verbose --directory --owner postgres --group postgres --mode 1777 /var/lib/postgresql 17 | 18 | # grab gosu for easy step-down from root 19 | # https://github.com/tianon/gosu/releases 20 | ENV GOSU_VERSION 1.17 21 | RUN set -eux; \ 22 | \ 23 | apk add --no-cache --virtual .gosu-deps \ 24 | ca-certificates \ 25 | dpkg \ 26 | gnupg \ 27 | ; \ 28 | \ 29 | dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \ 30 | wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \ 31 | wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \ 32 | \ 33 | # verify the signature 34 | export GNUPGHOME="$(mktemp -d)"; \ 35 | gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ 36 | gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \ 37 | gpgconf --kill all; \ 38 | rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \ 39 | \ 40 | # clean up fetch dependencies 41 | apk del --no-network .gosu-deps; \ 42 | \ 43 | chmod +x /usr/local/bin/gosu; \ 44 | # verify that the binary works 45 | gosu --version; \ 46 | gosu nobody true 47 | RUN set -eux; ln -svf gosu /usr/local/bin/su-exec; su-exec nobody true # backwards compatibility (removed in PostgreSQL 17+) 48 | 49 | # make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default 50 | # alpine doesn't require explicit locale-file generation 51 | ENV LANG en_US.utf8 52 | 53 | RUN mkdir /docker-entrypoint-initdb.d 54 | 55 | ENV PG_MAJOR 13 56 | ENV PG_VERSION 13.21 57 | ENV PG_SHA256 dcda1294df45f033b0656cf7a8e4afbbc624c25e1b144aec79530f74d7ef4ab4 58 | 59 | ENV DOCKER_PG_LLVM_DEPS \ 60 | llvm19-dev \ 61 | clang19 62 | 63 | RUN set -eux; \ 64 | \ 65 | wget -O postgresql.tar.bz2 "https://ftp.postgresql.org/pub/source/v$PG_VERSION/postgresql-$PG_VERSION.tar.bz2"; \ 66 | echo "$PG_SHA256 *postgresql.tar.bz2" | sha256sum -c -; \ 67 | mkdir -p /usr/src/postgresql; \ 68 | tar \ 69 | --extract \ 70 | --file postgresql.tar.bz2 \ 71 | --directory /usr/src/postgresql \ 72 | --strip-components 1 \ 73 | ; \ 74 | rm postgresql.tar.bz2; \ 75 | \ 76 | apk add --no-cache --virtual .build-deps \ 77 | $DOCKER_PG_LLVM_DEPS \ 78 | bison \ 79 | coreutils \ 80 | dpkg-dev dpkg \ 81 | flex \ 82 | g++ \ 83 | gcc \ 84 | krb5-dev \ 85 | libc-dev \ 86 | libedit-dev \ 87 | libxml2-dev \ 88 | libxslt-dev \ 89 | linux-headers \ 90 | make \ 91 | openldap-dev \ 92 | openssl-dev \ 93 | perl-dev \ 94 | perl-ipc-run \ 95 | perl-utils \ 96 | python3-dev \ 97 | tcl-dev \ 98 | util-linux-dev \ 99 | zlib-dev \ 100 | # https://www.postgresql.org/docs/10/static/release-10.html#id-1.11.6.9.5.13 101 | icu-dev \ 102 | ; \ 103 | \ 104 | cd /usr/src/postgresql; \ 105 | # update "DEFAULT_PGSOCKET_DIR" to "/var/run/postgresql" (matching Debian) 106 | # see https://anonscm.debian.org/git/pkg-postgresql/postgresql.git/tree/debian/patches/51-default-sockets-in-var.patch?id=8b539fcb3e093a521c095e70bdfa76887217b89f 107 | awk '$1 == "#define" && $2 == "DEFAULT_PGSOCKET_DIR" && $3 == "\"/tmp\"" { $3 = "\"/var/run/postgresql\""; print; next } { print }' src/include/pg_config_manual.h > src/include/pg_config_manual.h.new; \ 108 | grep '/var/run/postgresql' src/include/pg_config_manual.h.new; \ 109 | mv src/include/pg_config_manual.h.new src/include/pg_config_manual.h; \ 110 | gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \ 111 | \ 112 | # https://git.alpinelinux.org/aports/tree/community/postgresql15/APKBUILD?h=3.22-stable#n176 ("export LLVM_CONFIG") 113 | export LLVM_CONFIG="/usr/lib/llvm19/bin/llvm-config"; \ 114 | # https://git.alpinelinux.org/aports/tree/community/postgresql15/APKBUILD?h=3.22-stable#n180 ("older clang versions don't have a 'clang' exe anymore.") 115 | export CLANG=clang-19; \ 116 | \ 117 | # configure options taken from: 118 | # https://anonscm.debian.org/cgit/pkg-postgresql/postgresql.git/tree/debian/rules?h=9.5 119 | ./configure \ 120 | --enable-option-checking=fatal \ 121 | --build="$gnuArch" \ 122 | # "/usr/src/postgresql/src/backend/access/common/tupconvert.c:105: undefined reference to `libintl_gettext'" 123 | # --enable-nls \ 124 | --enable-integer-datetimes \ 125 | --enable-thread-safety \ 126 | --enable-tap-tests \ 127 | # skip debugging info -- we want tiny size instead 128 | # --enable-debug \ 129 | --disable-rpath \ 130 | --with-uuid=e2fs \ 131 | --with-gnu-ld \ 132 | --with-pgport=5432 \ 133 | --with-system-tzdata=/usr/share/zoneinfo \ 134 | --prefix=/usr/local \ 135 | --with-includes=/usr/local/include \ 136 | --with-libraries=/usr/local/lib \ 137 | --with-gssapi \ 138 | --with-ldap \ 139 | --with-tcl \ 140 | --with-perl \ 141 | --with-python \ 142 | # --with-pam \ 143 | --with-openssl \ 144 | --with-libxml \ 145 | --with-libxslt \ 146 | --with-icu \ 147 | --with-llvm \ 148 | ; \ 149 | make -j "$(nproc)" world-bin; \ 150 | make install-world-bin; \ 151 | make -C contrib install; \ 152 | \ 153 | runDeps="$( \ 154 | scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \ 155 | | tr ',' '\n' \ 156 | | sort -u \ 157 | | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ 158 | # Remove plperl, plpython and pltcl dependencies by default to save image size 159 | # To use the pl extensions, those have to be installed in a derived image 160 | | grep -v -e perl -e python -e tcl \ 161 | )"; \ 162 | apk add --no-cache --virtual .postgresql-rundeps \ 163 | $runDeps \ 164 | bash \ 165 | tzdata \ 166 | zstd \ 167 | # https://wiki.alpinelinux.org/wiki/Release_Notes_for_Alpine_3.16.0#ICU_data_split 168 | icu-data-full \ 169 | # https://git.alpinelinux.org/aports/tree/community/nss_wrapper/APKBUILD?h=3.22-stable#n7 ("ppc64le: test case segfaults") 170 | $([ "$(apk --print-arch)" != 'ppc64le' ] && echo 'nss_wrapper') \ 171 | ; \ 172 | apk del --no-network .build-deps; \ 173 | cd /; \ 174 | rm -rf \ 175 | /usr/src/postgresql \ 176 | /usr/local/share/doc \ 177 | /usr/local/share/man \ 178 | ; \ 179 | \ 180 | postgres --version 181 | 182 | # make the sample config easier to munge (and "correct by default") 183 | RUN set -eux; \ 184 | cp -v /usr/local/share/postgresql/postgresql.conf.sample /usr/local/share/postgresql/postgresql.conf.sample.orig; \ 185 | sed -ri "s!^#?(listen_addresses)\s*=\s*\S+.*!\1 = '*'!" /usr/local/share/postgresql/postgresql.conf.sample; \ 186 | grep -F "listen_addresses = '*'" /usr/local/share/postgresql/postgresql.conf.sample 187 | 188 | RUN install --verbose --directory --owner postgres --group postgres --mode 3777 /var/run/postgresql 189 | 190 | ENV PGDATA /var/lib/postgresql/data 191 | # this 1777 will be replaced by 0700 at runtime (allows semi-arbitrary "--user" values) 192 | RUN install --verbose --directory --owner postgres --group postgres --mode 1777 "$PGDATA" 193 | VOLUME /var/lib/postgresql/data 194 | 195 | COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ 196 | RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh 197 | ENTRYPOINT ["docker-entrypoint.sh"] 198 | 199 | # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL 200 | # calls "Fast Shutdown mode" wherein new connections are disallowed and any 201 | # in-progress transactions are aborted, allowing PostgreSQL to stop cleanly and 202 | # flush tables to disk. 203 | # 204 | # See https://www.postgresql.org/docs/current/server-shutdown.html for more details 205 | # about available PostgreSQL server shutdown signals. 206 | # 207 | # See also https://www.postgresql.org/docs/current/server-start.html for further 208 | # justification of this as the default value, namely that the example (and 209 | # shipped) systemd service files use the "Fast Shutdown mode" for service 210 | # termination. 211 | # 212 | STOPSIGNAL SIGINT 213 | # 214 | # An additional setting that is recommended for all users regardless of this 215 | # value is the runtime "--stop-timeout" (or your orchestrator/runtime's 216 | # equivalent) for controlling how long to wait between sending the defined 217 | # STOPSIGNAL and sending SIGKILL. 218 | # 219 | # The default in most runtimes (such as Docker) is 10 seconds, and the 220 | # documentation at https://www.postgresql.org/docs/current/server-start.html notes 221 | # that even 90 seconds may not be long enough in many instances. 222 | 223 | EXPOSE 5432 224 | CMD ["postgres"] 225 | -------------------------------------------------------------------------------- /13/alpine3.22/docker-ensure-initdb.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | # 5 | # This script is intended for three main use cases: 6 | # 7 | # 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior 8 | # 9 | # 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution 10 | # (no-op if database is already initialized) 11 | # 12 | # 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use 13 | # (error if database is already initialized) 14 | # 15 | 16 | source /usr/local/bin/docker-entrypoint.sh 17 | 18 | # arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) 19 | if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then 20 | set -- postgres "$@" 21 | fi 22 | 23 | # see also "_main" in "docker-entrypoint.sh" 24 | 25 | docker_setup_env 26 | # setup data directories and permissions (when run as root) 27 | docker_create_db_directories 28 | if [ "$(id -u)" = '0' ]; then 29 | # then restart script as postgres user 30 | exec gosu postgres "$BASH_SOURCE" "$@" 31 | fi 32 | 33 | # only run initialization on an empty data directory 34 | if [ -z "$DATABASE_ALREADY_EXISTS" ]; then 35 | docker_verify_minimum_env 36 | 37 | # check dir permissions to reduce likelihood of half-initialized database 38 | ls /docker-entrypoint-initdb.d/ > /dev/null 39 | 40 | docker_init_database_dir 41 | pg_setup_hba_conf "$@" 42 | 43 | # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless 44 | # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS 45 | export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" 46 | docker_temp_server_start "$@" 47 | 48 | docker_setup_db 49 | docker_process_init_files /docker-entrypoint-initdb.d/* 50 | 51 | docker_temp_server_stop 52 | unset PGPASSWORD 53 | else 54 | self="$(basename "$0")" 55 | case "$self" in 56 | docker-ensure-initdb.sh) 57 | echo >&2 "$self: note: database already initialized in '$PGDATA'!" 58 | exit 0 59 | ;; 60 | 61 | docker-enforce-initdb.sh) 62 | echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" 63 | exit 1 64 | ;; 65 | 66 | *) 67 | echo >&2 "$self: error: unknown file name: $self" 68 | exit 99 69 | ;; 70 | esac 71 | fi 72 | -------------------------------------------------------------------------------- /13/bookworm/docker-ensure-initdb.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | # 5 | # This script is intended for three main use cases: 6 | # 7 | # 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior 8 | # 9 | # 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution 10 | # (no-op if database is already initialized) 11 | # 12 | # 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use 13 | # (error if database is already initialized) 14 | # 15 | 16 | source /usr/local/bin/docker-entrypoint.sh 17 | 18 | # arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) 19 | if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then 20 | set -- postgres "$@" 21 | fi 22 | 23 | # see also "_main" in "docker-entrypoint.sh" 24 | 25 | docker_setup_env 26 | # setup data directories and permissions (when run as root) 27 | docker_create_db_directories 28 | if [ "$(id -u)" = '0' ]; then 29 | # then restart script as postgres user 30 | exec gosu postgres "$BASH_SOURCE" "$@" 31 | fi 32 | 33 | # only run initialization on an empty data directory 34 | if [ -z "$DATABASE_ALREADY_EXISTS" ]; then 35 | docker_verify_minimum_env 36 | 37 | # check dir permissions to reduce likelihood of half-initialized database 38 | ls /docker-entrypoint-initdb.d/ > /dev/null 39 | 40 | docker_init_database_dir 41 | pg_setup_hba_conf "$@" 42 | 43 | # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless 44 | # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS 45 | export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" 46 | docker_temp_server_start "$@" 47 | 48 | docker_setup_db 49 | docker_process_init_files /docker-entrypoint-initdb.d/* 50 | 51 | docker_temp_server_stop 52 | unset PGPASSWORD 53 | else 54 | self="$(basename "$0")" 55 | case "$self" in 56 | docker-ensure-initdb.sh) 57 | echo >&2 "$self: note: database already initialized in '$PGDATA'!" 58 | exit 0 59 | ;; 60 | 61 | docker-enforce-initdb.sh) 62 | echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" 63 | exit 1 64 | ;; 65 | 66 | *) 67 | echo >&2 "$self: error: unknown file name: $self" 68 | exit 99 69 | ;; 70 | esac 71 | fi 72 | -------------------------------------------------------------------------------- /13/bullseye/docker-ensure-initdb.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | # 5 | # This script is intended for three main use cases: 6 | # 7 | # 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior 8 | # 9 | # 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution 10 | # (no-op if database is already initialized) 11 | # 12 | # 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use 13 | # (error if database is already initialized) 14 | # 15 | 16 | source /usr/local/bin/docker-entrypoint.sh 17 | 18 | # arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) 19 | if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then 20 | set -- postgres "$@" 21 | fi 22 | 23 | # see also "_main" in "docker-entrypoint.sh" 24 | 25 | docker_setup_env 26 | # setup data directories and permissions (when run as root) 27 | docker_create_db_directories 28 | if [ "$(id -u)" = '0' ]; then 29 | # then restart script as postgres user 30 | exec gosu postgres "$BASH_SOURCE" "$@" 31 | fi 32 | 33 | # only run initialization on an empty data directory 34 | if [ -z "$DATABASE_ALREADY_EXISTS" ]; then 35 | docker_verify_minimum_env 36 | 37 | # check dir permissions to reduce likelihood of half-initialized database 38 | ls /docker-entrypoint-initdb.d/ > /dev/null 39 | 40 | docker_init_database_dir 41 | pg_setup_hba_conf "$@" 42 | 43 | # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless 44 | # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS 45 | export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" 46 | docker_temp_server_start "$@" 47 | 48 | docker_setup_db 49 | docker_process_init_files /docker-entrypoint-initdb.d/* 50 | 51 | docker_temp_server_stop 52 | unset PGPASSWORD 53 | else 54 | self="$(basename "$0")" 55 | case "$self" in 56 | docker-ensure-initdb.sh) 57 | echo >&2 "$self: note: database already initialized in '$PGDATA'!" 58 | exit 0 59 | ;; 60 | 61 | docker-enforce-initdb.sh) 62 | echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" 63 | exit 1 64 | ;; 65 | 66 | *) 67 | echo >&2 "$self: error: unknown file name: $self" 68 | exit 99 69 | ;; 70 | esac 71 | fi 72 | -------------------------------------------------------------------------------- /14/alpine3.21/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" 3 | # 4 | # PLEASE DO NOT EDIT IT DIRECTLY. 5 | # 6 | 7 | FROM alpine:3.21 8 | 9 | # 70 is the standard uid/gid for "postgres" in Alpine 10 | # https://git.alpinelinux.org/aports/tree/main/postgresql-common/postgresql-common.pre-install?h=3.22-stable 11 | RUN set -eux; \ 12 | addgroup -g 70 -S postgres; \ 13 | adduser -u 70 -S -D -G postgres -H -h /var/lib/postgresql -s /bin/sh postgres; \ 14 | # also create the postgres user's home directory with appropriate permissions 15 | # see https://github.com/docker-library/postgres/issues/274 16 | install --verbose --directory --owner postgres --group postgres --mode 1777 /var/lib/postgresql 17 | 18 | # grab gosu for easy step-down from root 19 | # https://github.com/tianon/gosu/releases 20 | ENV GOSU_VERSION 1.17 21 | RUN set -eux; \ 22 | \ 23 | apk add --no-cache --virtual .gosu-deps \ 24 | ca-certificates \ 25 | dpkg \ 26 | gnupg \ 27 | ; \ 28 | \ 29 | dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \ 30 | wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \ 31 | wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \ 32 | \ 33 | # verify the signature 34 | export GNUPGHOME="$(mktemp -d)"; \ 35 | gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ 36 | gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \ 37 | gpgconf --kill all; \ 38 | rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \ 39 | \ 40 | # clean up fetch dependencies 41 | apk del --no-network .gosu-deps; \ 42 | \ 43 | chmod +x /usr/local/bin/gosu; \ 44 | # verify that the binary works 45 | gosu --version; \ 46 | gosu nobody true 47 | RUN set -eux; ln -svf gosu /usr/local/bin/su-exec; su-exec nobody true # backwards compatibility (removed in PostgreSQL 17+) 48 | 49 | # make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default 50 | # alpine doesn't require explicit locale-file generation 51 | ENV LANG en_US.utf8 52 | 53 | RUN mkdir /docker-entrypoint-initdb.d 54 | 55 | ENV PG_MAJOR 14 56 | ENV PG_VERSION 14.18 57 | ENV PG_SHA256 83ab29d6bfc3dc58b2ed3c664114fdfbeb6a0450c4b8d7fa69aee91e3ca14f8e 58 | 59 | ENV DOCKER_PG_LLVM_DEPS \ 60 | llvm19-dev \ 61 | clang19 62 | 63 | RUN set -eux; \ 64 | \ 65 | wget -O postgresql.tar.bz2 "https://ftp.postgresql.org/pub/source/v$PG_VERSION/postgresql-$PG_VERSION.tar.bz2"; \ 66 | echo "$PG_SHA256 *postgresql.tar.bz2" | sha256sum -c -; \ 67 | mkdir -p /usr/src/postgresql; \ 68 | tar \ 69 | --extract \ 70 | --file postgresql.tar.bz2 \ 71 | --directory /usr/src/postgresql \ 72 | --strip-components 1 \ 73 | ; \ 74 | rm postgresql.tar.bz2; \ 75 | \ 76 | apk add --no-cache --virtual .build-deps \ 77 | $DOCKER_PG_LLVM_DEPS \ 78 | bison \ 79 | coreutils \ 80 | dpkg-dev dpkg \ 81 | flex \ 82 | g++ \ 83 | gcc \ 84 | krb5-dev \ 85 | libc-dev \ 86 | libedit-dev \ 87 | libxml2-dev \ 88 | libxslt-dev \ 89 | linux-headers \ 90 | make \ 91 | openldap-dev \ 92 | openssl-dev \ 93 | perl-dev \ 94 | perl-ipc-run \ 95 | perl-utils \ 96 | python3-dev \ 97 | tcl-dev \ 98 | util-linux-dev \ 99 | zlib-dev \ 100 | # https://www.postgresql.org/docs/10/static/release-10.html#id-1.11.6.9.5.13 101 | icu-dev \ 102 | # https://www.postgresql.org/docs/14/release-14.html#id-1.11.6.5.5.3.7 103 | lz4-dev \ 104 | ; \ 105 | \ 106 | cd /usr/src/postgresql; \ 107 | # update "DEFAULT_PGSOCKET_DIR" to "/var/run/postgresql" (matching Debian) 108 | # see https://anonscm.debian.org/git/pkg-postgresql/postgresql.git/tree/debian/patches/51-default-sockets-in-var.patch?id=8b539fcb3e093a521c095e70bdfa76887217b89f 109 | awk '$1 == "#define" && $2 == "DEFAULT_PGSOCKET_DIR" && $3 == "\"/tmp\"" { $3 = "\"/var/run/postgresql\""; print; next } { print }' src/include/pg_config_manual.h > src/include/pg_config_manual.h.new; \ 110 | grep '/var/run/postgresql' src/include/pg_config_manual.h.new; \ 111 | mv src/include/pg_config_manual.h.new src/include/pg_config_manual.h; \ 112 | gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \ 113 | \ 114 | # https://git.alpinelinux.org/aports/tree/community/postgresql15/APKBUILD?h=3.22-stable#n176 ("export LLVM_CONFIG") 115 | export LLVM_CONFIG="/usr/lib/llvm19/bin/llvm-config"; \ 116 | # https://git.alpinelinux.org/aports/tree/community/postgresql15/APKBUILD?h=3.22-stable#n180 ("older clang versions don't have a 'clang' exe anymore.") 117 | export CLANG=clang-19; \ 118 | \ 119 | # configure options taken from: 120 | # https://anonscm.debian.org/cgit/pkg-postgresql/postgresql.git/tree/debian/rules?h=9.5 121 | ./configure \ 122 | --enable-option-checking=fatal \ 123 | --build="$gnuArch" \ 124 | # "/usr/src/postgresql/src/backend/access/common/tupconvert.c:105: undefined reference to `libintl_gettext'" 125 | # --enable-nls \ 126 | --enable-integer-datetimes \ 127 | --enable-thread-safety \ 128 | --enable-tap-tests \ 129 | # skip debugging info -- we want tiny size instead 130 | # --enable-debug \ 131 | --disable-rpath \ 132 | --with-uuid=e2fs \ 133 | --with-gnu-ld \ 134 | --with-pgport=5432 \ 135 | --with-system-tzdata=/usr/share/zoneinfo \ 136 | --prefix=/usr/local \ 137 | --with-includes=/usr/local/include \ 138 | --with-libraries=/usr/local/lib \ 139 | --with-gssapi \ 140 | --with-ldap \ 141 | --with-tcl \ 142 | --with-perl \ 143 | --with-python \ 144 | # --with-pam \ 145 | --with-openssl \ 146 | --with-libxml \ 147 | --with-libxslt \ 148 | --with-icu \ 149 | --with-llvm \ 150 | --with-lz4 \ 151 | ; \ 152 | make -j "$(nproc)" world-bin; \ 153 | make install-world-bin; \ 154 | make -C contrib install; \ 155 | \ 156 | runDeps="$( \ 157 | scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \ 158 | | tr ',' '\n' \ 159 | | sort -u \ 160 | | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ 161 | # Remove plperl, plpython and pltcl dependencies by default to save image size 162 | # To use the pl extensions, those have to be installed in a derived image 163 | | grep -v -e perl -e python -e tcl \ 164 | )"; \ 165 | apk add --no-cache --virtual .postgresql-rundeps \ 166 | $runDeps \ 167 | bash \ 168 | tzdata \ 169 | zstd \ 170 | # https://wiki.alpinelinux.org/wiki/Release_Notes_for_Alpine_3.16.0#ICU_data_split 171 | icu-data-full \ 172 | # https://git.alpinelinux.org/aports/tree/community/nss_wrapper/APKBUILD?h=3.22-stable#n7 ("ppc64le: test case segfaults") 173 | $([ "$(apk --print-arch)" != 'ppc64le' ] && echo 'nss_wrapper') \ 174 | ; \ 175 | apk del --no-network .build-deps; \ 176 | cd /; \ 177 | rm -rf \ 178 | /usr/src/postgresql \ 179 | /usr/local/share/doc \ 180 | /usr/local/share/man \ 181 | ; \ 182 | \ 183 | postgres --version 184 | 185 | # make the sample config easier to munge (and "correct by default") 186 | RUN set -eux; \ 187 | cp -v /usr/local/share/postgresql/postgresql.conf.sample /usr/local/share/postgresql/postgresql.conf.sample.orig; \ 188 | sed -ri "s!^#?(listen_addresses)\s*=\s*\S+.*!\1 = '*'!" /usr/local/share/postgresql/postgresql.conf.sample; \ 189 | grep -F "listen_addresses = '*'" /usr/local/share/postgresql/postgresql.conf.sample 190 | 191 | RUN install --verbose --directory --owner postgres --group postgres --mode 3777 /var/run/postgresql 192 | 193 | ENV PGDATA /var/lib/postgresql/data 194 | # this 1777 will be replaced by 0700 at runtime (allows semi-arbitrary "--user" values) 195 | RUN install --verbose --directory --owner postgres --group postgres --mode 1777 "$PGDATA" 196 | VOLUME /var/lib/postgresql/data 197 | 198 | COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ 199 | RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh 200 | ENTRYPOINT ["docker-entrypoint.sh"] 201 | 202 | # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL 203 | # calls "Fast Shutdown mode" wherein new connections are disallowed and any 204 | # in-progress transactions are aborted, allowing PostgreSQL to stop cleanly and 205 | # flush tables to disk. 206 | # 207 | # See https://www.postgresql.org/docs/current/server-shutdown.html for more details 208 | # about available PostgreSQL server shutdown signals. 209 | # 210 | # See also https://www.postgresql.org/docs/current/server-start.html for further 211 | # justification of this as the default value, namely that the example (and 212 | # shipped) systemd service files use the "Fast Shutdown mode" for service 213 | # termination. 214 | # 215 | STOPSIGNAL SIGINT 216 | # 217 | # An additional setting that is recommended for all users regardless of this 218 | # value is the runtime "--stop-timeout" (or your orchestrator/runtime's 219 | # equivalent) for controlling how long to wait between sending the defined 220 | # STOPSIGNAL and sending SIGKILL. 221 | # 222 | # The default in most runtimes (such as Docker) is 10 seconds, and the 223 | # documentation at https://www.postgresql.org/docs/current/server-start.html notes 224 | # that even 90 seconds may not be long enough in many instances. 225 | 226 | EXPOSE 5432 227 | CMD ["postgres"] 228 | -------------------------------------------------------------------------------- /14/alpine3.21/docker-ensure-initdb.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | # 5 | # This script is intended for three main use cases: 6 | # 7 | # 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior 8 | # 9 | # 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution 10 | # (no-op if database is already initialized) 11 | # 12 | # 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use 13 | # (error if database is already initialized) 14 | # 15 | 16 | source /usr/local/bin/docker-entrypoint.sh 17 | 18 | # arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) 19 | if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then 20 | set -- postgres "$@" 21 | fi 22 | 23 | # see also "_main" in "docker-entrypoint.sh" 24 | 25 | docker_setup_env 26 | # setup data directories and permissions (when run as root) 27 | docker_create_db_directories 28 | if [ "$(id -u)" = '0' ]; then 29 | # then restart script as postgres user 30 | exec gosu postgres "$BASH_SOURCE" "$@" 31 | fi 32 | 33 | # only run initialization on an empty data directory 34 | if [ -z "$DATABASE_ALREADY_EXISTS" ]; then 35 | docker_verify_minimum_env 36 | 37 | # check dir permissions to reduce likelihood of half-initialized database 38 | ls /docker-entrypoint-initdb.d/ > /dev/null 39 | 40 | docker_init_database_dir 41 | pg_setup_hba_conf "$@" 42 | 43 | # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless 44 | # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS 45 | export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" 46 | docker_temp_server_start "$@" 47 | 48 | docker_setup_db 49 | docker_process_init_files /docker-entrypoint-initdb.d/* 50 | 51 | docker_temp_server_stop 52 | unset PGPASSWORD 53 | else 54 | self="$(basename "$0")" 55 | case "$self" in 56 | docker-ensure-initdb.sh) 57 | echo >&2 "$self: note: database already initialized in '$PGDATA'!" 58 | exit 0 59 | ;; 60 | 61 | docker-enforce-initdb.sh) 62 | echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" 63 | exit 1 64 | ;; 65 | 66 | *) 67 | echo >&2 "$self: error: unknown file name: $self" 68 | exit 99 69 | ;; 70 | esac 71 | fi 72 | -------------------------------------------------------------------------------- /14/alpine3.22/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" 3 | # 4 | # PLEASE DO NOT EDIT IT DIRECTLY. 5 | # 6 | 7 | FROM alpine:3.22 8 | 9 | # 70 is the standard uid/gid for "postgres" in Alpine 10 | # https://git.alpinelinux.org/aports/tree/main/postgresql-common/postgresql-common.pre-install?h=3.22-stable 11 | RUN set -eux; \ 12 | addgroup -g 70 -S postgres; \ 13 | adduser -u 70 -S -D -G postgres -H -h /var/lib/postgresql -s /bin/sh postgres; \ 14 | # also create the postgres user's home directory with appropriate permissions 15 | # see https://github.com/docker-library/postgres/issues/274 16 | install --verbose --directory --owner postgres --group postgres --mode 1777 /var/lib/postgresql 17 | 18 | # grab gosu for easy step-down from root 19 | # https://github.com/tianon/gosu/releases 20 | ENV GOSU_VERSION 1.17 21 | RUN set -eux; \ 22 | \ 23 | apk add --no-cache --virtual .gosu-deps \ 24 | ca-certificates \ 25 | dpkg \ 26 | gnupg \ 27 | ; \ 28 | \ 29 | dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \ 30 | wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \ 31 | wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \ 32 | \ 33 | # verify the signature 34 | export GNUPGHOME="$(mktemp -d)"; \ 35 | gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ 36 | gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \ 37 | gpgconf --kill all; \ 38 | rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \ 39 | \ 40 | # clean up fetch dependencies 41 | apk del --no-network .gosu-deps; \ 42 | \ 43 | chmod +x /usr/local/bin/gosu; \ 44 | # verify that the binary works 45 | gosu --version; \ 46 | gosu nobody true 47 | RUN set -eux; ln -svf gosu /usr/local/bin/su-exec; su-exec nobody true # backwards compatibility (removed in PostgreSQL 17+) 48 | 49 | # make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default 50 | # alpine doesn't require explicit locale-file generation 51 | ENV LANG en_US.utf8 52 | 53 | RUN mkdir /docker-entrypoint-initdb.d 54 | 55 | ENV PG_MAJOR 14 56 | ENV PG_VERSION 14.18 57 | ENV PG_SHA256 83ab29d6bfc3dc58b2ed3c664114fdfbeb6a0450c4b8d7fa69aee91e3ca14f8e 58 | 59 | ENV DOCKER_PG_LLVM_DEPS \ 60 | llvm19-dev \ 61 | clang19 62 | 63 | RUN set -eux; \ 64 | \ 65 | wget -O postgresql.tar.bz2 "https://ftp.postgresql.org/pub/source/v$PG_VERSION/postgresql-$PG_VERSION.tar.bz2"; \ 66 | echo "$PG_SHA256 *postgresql.tar.bz2" | sha256sum -c -; \ 67 | mkdir -p /usr/src/postgresql; \ 68 | tar \ 69 | --extract \ 70 | --file postgresql.tar.bz2 \ 71 | --directory /usr/src/postgresql \ 72 | --strip-components 1 \ 73 | ; \ 74 | rm postgresql.tar.bz2; \ 75 | \ 76 | apk add --no-cache --virtual .build-deps \ 77 | $DOCKER_PG_LLVM_DEPS \ 78 | bison \ 79 | coreutils \ 80 | dpkg-dev dpkg \ 81 | flex \ 82 | g++ \ 83 | gcc \ 84 | krb5-dev \ 85 | libc-dev \ 86 | libedit-dev \ 87 | libxml2-dev \ 88 | libxslt-dev \ 89 | linux-headers \ 90 | make \ 91 | openldap-dev \ 92 | openssl-dev \ 93 | perl-dev \ 94 | perl-ipc-run \ 95 | perl-utils \ 96 | python3-dev \ 97 | tcl-dev \ 98 | util-linux-dev \ 99 | zlib-dev \ 100 | # https://www.postgresql.org/docs/10/static/release-10.html#id-1.11.6.9.5.13 101 | icu-dev \ 102 | # https://www.postgresql.org/docs/14/release-14.html#id-1.11.6.5.5.3.7 103 | lz4-dev \ 104 | ; \ 105 | \ 106 | cd /usr/src/postgresql; \ 107 | # update "DEFAULT_PGSOCKET_DIR" to "/var/run/postgresql" (matching Debian) 108 | # see https://anonscm.debian.org/git/pkg-postgresql/postgresql.git/tree/debian/patches/51-default-sockets-in-var.patch?id=8b539fcb3e093a521c095e70bdfa76887217b89f 109 | awk '$1 == "#define" && $2 == "DEFAULT_PGSOCKET_DIR" && $3 == "\"/tmp\"" { $3 = "\"/var/run/postgresql\""; print; next } { print }' src/include/pg_config_manual.h > src/include/pg_config_manual.h.new; \ 110 | grep '/var/run/postgresql' src/include/pg_config_manual.h.new; \ 111 | mv src/include/pg_config_manual.h.new src/include/pg_config_manual.h; \ 112 | gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \ 113 | \ 114 | # https://git.alpinelinux.org/aports/tree/community/postgresql15/APKBUILD?h=3.22-stable#n176 ("export LLVM_CONFIG") 115 | export LLVM_CONFIG="/usr/lib/llvm19/bin/llvm-config"; \ 116 | # https://git.alpinelinux.org/aports/tree/community/postgresql15/APKBUILD?h=3.22-stable#n180 ("older clang versions don't have a 'clang' exe anymore.") 117 | export CLANG=clang-19; \ 118 | \ 119 | # configure options taken from: 120 | # https://anonscm.debian.org/cgit/pkg-postgresql/postgresql.git/tree/debian/rules?h=9.5 121 | ./configure \ 122 | --enable-option-checking=fatal \ 123 | --build="$gnuArch" \ 124 | # "/usr/src/postgresql/src/backend/access/common/tupconvert.c:105: undefined reference to `libintl_gettext'" 125 | # --enable-nls \ 126 | --enable-integer-datetimes \ 127 | --enable-thread-safety \ 128 | --enable-tap-tests \ 129 | # skip debugging info -- we want tiny size instead 130 | # --enable-debug \ 131 | --disable-rpath \ 132 | --with-uuid=e2fs \ 133 | --with-gnu-ld \ 134 | --with-pgport=5432 \ 135 | --with-system-tzdata=/usr/share/zoneinfo \ 136 | --prefix=/usr/local \ 137 | --with-includes=/usr/local/include \ 138 | --with-libraries=/usr/local/lib \ 139 | --with-gssapi \ 140 | --with-ldap \ 141 | --with-tcl \ 142 | --with-perl \ 143 | --with-python \ 144 | # --with-pam \ 145 | --with-openssl \ 146 | --with-libxml \ 147 | --with-libxslt \ 148 | --with-icu \ 149 | --with-llvm \ 150 | --with-lz4 \ 151 | ; \ 152 | make -j "$(nproc)" world-bin; \ 153 | make install-world-bin; \ 154 | make -C contrib install; \ 155 | \ 156 | runDeps="$( \ 157 | scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \ 158 | | tr ',' '\n' \ 159 | | sort -u \ 160 | | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ 161 | # Remove plperl, plpython and pltcl dependencies by default to save image size 162 | # To use the pl extensions, those have to be installed in a derived image 163 | | grep -v -e perl -e python -e tcl \ 164 | )"; \ 165 | apk add --no-cache --virtual .postgresql-rundeps \ 166 | $runDeps \ 167 | bash \ 168 | tzdata \ 169 | zstd \ 170 | # https://wiki.alpinelinux.org/wiki/Release_Notes_for_Alpine_3.16.0#ICU_data_split 171 | icu-data-full \ 172 | # https://git.alpinelinux.org/aports/tree/community/nss_wrapper/APKBUILD?h=3.22-stable#n7 ("ppc64le: test case segfaults") 173 | $([ "$(apk --print-arch)" != 'ppc64le' ] && echo 'nss_wrapper') \ 174 | ; \ 175 | apk del --no-network .build-deps; \ 176 | cd /; \ 177 | rm -rf \ 178 | /usr/src/postgresql \ 179 | /usr/local/share/doc \ 180 | /usr/local/share/man \ 181 | ; \ 182 | \ 183 | postgres --version 184 | 185 | # make the sample config easier to munge (and "correct by default") 186 | RUN set -eux; \ 187 | cp -v /usr/local/share/postgresql/postgresql.conf.sample /usr/local/share/postgresql/postgresql.conf.sample.orig; \ 188 | sed -ri "s!^#?(listen_addresses)\s*=\s*\S+.*!\1 = '*'!" /usr/local/share/postgresql/postgresql.conf.sample; \ 189 | grep -F "listen_addresses = '*'" /usr/local/share/postgresql/postgresql.conf.sample 190 | 191 | RUN install --verbose --directory --owner postgres --group postgres --mode 3777 /var/run/postgresql 192 | 193 | ENV PGDATA /var/lib/postgresql/data 194 | # this 1777 will be replaced by 0700 at runtime (allows semi-arbitrary "--user" values) 195 | RUN install --verbose --directory --owner postgres --group postgres --mode 1777 "$PGDATA" 196 | VOLUME /var/lib/postgresql/data 197 | 198 | COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ 199 | RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh 200 | ENTRYPOINT ["docker-entrypoint.sh"] 201 | 202 | # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL 203 | # calls "Fast Shutdown mode" wherein new connections are disallowed and any 204 | # in-progress transactions are aborted, allowing PostgreSQL to stop cleanly and 205 | # flush tables to disk. 206 | # 207 | # See https://www.postgresql.org/docs/current/server-shutdown.html for more details 208 | # about available PostgreSQL server shutdown signals. 209 | # 210 | # See also https://www.postgresql.org/docs/current/server-start.html for further 211 | # justification of this as the default value, namely that the example (and 212 | # shipped) systemd service files use the "Fast Shutdown mode" for service 213 | # termination. 214 | # 215 | STOPSIGNAL SIGINT 216 | # 217 | # An additional setting that is recommended for all users regardless of this 218 | # value is the runtime "--stop-timeout" (or your orchestrator/runtime's 219 | # equivalent) for controlling how long to wait between sending the defined 220 | # STOPSIGNAL and sending SIGKILL. 221 | # 222 | # The default in most runtimes (such as Docker) is 10 seconds, and the 223 | # documentation at https://www.postgresql.org/docs/current/server-start.html notes 224 | # that even 90 seconds may not be long enough in many instances. 225 | 226 | EXPOSE 5432 227 | CMD ["postgres"] 228 | -------------------------------------------------------------------------------- /14/alpine3.22/docker-ensure-initdb.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | # 5 | # This script is intended for three main use cases: 6 | # 7 | # 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior 8 | # 9 | # 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution 10 | # (no-op if database is already initialized) 11 | # 12 | # 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use 13 | # (error if database is already initialized) 14 | # 15 | 16 | source /usr/local/bin/docker-entrypoint.sh 17 | 18 | # arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) 19 | if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then 20 | set -- postgres "$@" 21 | fi 22 | 23 | # see also "_main" in "docker-entrypoint.sh" 24 | 25 | docker_setup_env 26 | # setup data directories and permissions (when run as root) 27 | docker_create_db_directories 28 | if [ "$(id -u)" = '0' ]; then 29 | # then restart script as postgres user 30 | exec gosu postgres "$BASH_SOURCE" "$@" 31 | fi 32 | 33 | # only run initialization on an empty data directory 34 | if [ -z "$DATABASE_ALREADY_EXISTS" ]; then 35 | docker_verify_minimum_env 36 | 37 | # check dir permissions to reduce likelihood of half-initialized database 38 | ls /docker-entrypoint-initdb.d/ > /dev/null 39 | 40 | docker_init_database_dir 41 | pg_setup_hba_conf "$@" 42 | 43 | # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless 44 | # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS 45 | export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" 46 | docker_temp_server_start "$@" 47 | 48 | docker_setup_db 49 | docker_process_init_files /docker-entrypoint-initdb.d/* 50 | 51 | docker_temp_server_stop 52 | unset PGPASSWORD 53 | else 54 | self="$(basename "$0")" 55 | case "$self" in 56 | docker-ensure-initdb.sh) 57 | echo >&2 "$self: note: database already initialized in '$PGDATA'!" 58 | exit 0 59 | ;; 60 | 61 | docker-enforce-initdb.sh) 62 | echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" 63 | exit 1 64 | ;; 65 | 66 | *) 67 | echo >&2 "$self: error: unknown file name: $self" 68 | exit 99 69 | ;; 70 | esac 71 | fi 72 | -------------------------------------------------------------------------------- /14/bookworm/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" 3 | # 4 | # PLEASE DO NOT EDIT IT DIRECTLY. 5 | # 6 | 7 | FROM debian:bookworm-slim 8 | 9 | # explicitly set user/group IDs 10 | RUN set -eux; \ 11 | groupadd -r postgres --gid=999; \ 12 | # https://salsa.debian.org/postgresql/postgresql-common/blob/997d842ee744687d99a2b2d95c1083a2615c79e8/debian/postgresql-common.postinst#L32-35 13 | useradd -r -g postgres --uid=999 --home-dir=/var/lib/postgresql --shell=/bin/bash postgres; \ 14 | # also create the postgres user's home directory with appropriate permissions 15 | # see https://github.com/docker-library/postgres/issues/274 16 | install --verbose --directory --owner postgres --group postgres --mode 1777 /var/lib/postgresql 17 | 18 | RUN set -ex; \ 19 | apt-get update; \ 20 | apt-get install -y --no-install-recommends \ 21 | gnupg \ 22 | # https://www.postgresql.org/docs/16/app-psql.html#APP-PSQL-META-COMMAND-PSET-PAGER 23 | # https://github.com/postgres/postgres/blob/REL_16_1/src/include/fe_utils/print.h#L25 24 | # (if "less" is available, it gets used as the default pager for psql, and it only adds ~1.5MiB to our image size) 25 | less \ 26 | ; \ 27 | rm -rf /var/lib/apt/lists/* 28 | 29 | # grab gosu for easy step-down from root 30 | # https://github.com/tianon/gosu/releases 31 | ENV GOSU_VERSION 1.17 32 | RUN set -eux; \ 33 | savedAptMark="$(apt-mark showmanual)"; \ 34 | apt-get update; \ 35 | apt-get install -y --no-install-recommends ca-certificates wget; \ 36 | rm -rf /var/lib/apt/lists/*; \ 37 | dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \ 38 | wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \ 39 | wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \ 40 | export GNUPGHOME="$(mktemp -d)"; \ 41 | gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ 42 | gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \ 43 | gpgconf --kill all; \ 44 | rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \ 45 | apt-mark auto '.*' > /dev/null; \ 46 | [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; \ 47 | apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ 48 | chmod +x /usr/local/bin/gosu; \ 49 | gosu --version; \ 50 | gosu nobody true 51 | 52 | # make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default 53 | RUN set -eux; \ 54 | if [ -f /etc/dpkg/dpkg.cfg.d/docker ]; then \ 55 | # if this file exists, we're likely in "debian:xxx-slim", and locales are thus being excluded so we need to remove that exclusion (since we need locales) 56 | grep -q '/usr/share/locale' /etc/dpkg/dpkg.cfg.d/docker; \ 57 | sed -ri '/\/usr\/share\/locale/d' /etc/dpkg/dpkg.cfg.d/docker; \ 58 | ! grep -q '/usr/share/locale' /etc/dpkg/dpkg.cfg.d/docker; \ 59 | fi; \ 60 | apt-get update; apt-get install -y --no-install-recommends locales; rm -rf /var/lib/apt/lists/*; \ 61 | echo 'en_US.UTF-8 UTF-8' >> /etc/locale.gen; \ 62 | locale-gen; \ 63 | locale -a | grep 'en_US.utf8' 64 | ENV LANG en_US.utf8 65 | 66 | RUN set -eux; \ 67 | apt-get update; \ 68 | apt-get install -y --no-install-recommends \ 69 | libnss-wrapper \ 70 | xz-utils \ 71 | zstd \ 72 | ; \ 73 | rm -rf /var/lib/apt/lists/* 74 | 75 | RUN mkdir /docker-entrypoint-initdb.d 76 | 77 | RUN set -ex; \ 78 | # pub 4096R/ACCC4CF8 2011-10-13 [expires: 2019-07-02] 79 | # Key fingerprint = B97B 0AFC AA1A 47F0 44F2 44A0 7FCC 7D46 ACCC 4CF8 80 | # uid PostgreSQL Debian Repository 81 | key='B97B0AFCAA1A47F044F244A07FCC7D46ACCC4CF8'; \ 82 | export GNUPGHOME="$(mktemp -d)"; \ 83 | mkdir -p /usr/local/share/keyrings/; \ 84 | gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \ 85 | gpg --batch --export --armor "$key" > /usr/local/share/keyrings/postgres.gpg.asc; \ 86 | gpgconf --kill all; \ 87 | rm -rf "$GNUPGHOME" 88 | 89 | ENV PG_MAJOR 14 90 | ENV PATH $PATH:/usr/lib/postgresql/$PG_MAJOR/bin 91 | 92 | ENV PG_VERSION 14.18-1.pgdg120+1 93 | 94 | RUN set -ex; \ 95 | \ 96 | # see note below about "*.pyc" files 97 | export PYTHONDONTWRITEBYTECODE=1; \ 98 | \ 99 | dpkgArch="$(dpkg --print-architecture)"; \ 100 | aptRepo="[ signed-by=/usr/local/share/keyrings/postgres.gpg.asc ] http://apt.postgresql.org/pub/repos/apt/ bookworm-pgdg main $PG_MAJOR"; \ 101 | case "$dpkgArch" in \ 102 | amd64 | arm64 | ppc64el) \ 103 | # arches officialy built by upstream 104 | echo "deb $aptRepo" > /etc/apt/sources.list.d/pgdg.list; \ 105 | apt-get update; \ 106 | ;; \ 107 | *) \ 108 | # we're on an architecture upstream doesn't officially build for 109 | # let's build binaries from their published source packages 110 | echo "deb-src $aptRepo" > /etc/apt/sources.list.d/pgdg.list; \ 111 | \ 112 | savedAptMark="$(apt-mark showmanual)"; \ 113 | \ 114 | tempDir="$(mktemp -d)"; \ 115 | cd "$tempDir"; \ 116 | \ 117 | # create a temporary local APT repo to install from (so that dependency resolution can be handled by APT, as it should be) 118 | apt-get update; \ 119 | apt-get install -y --no-install-recommends dpkg-dev; \ 120 | echo "deb [ trusted=yes ] file://$tempDir ./" > /etc/apt/sources.list.d/temp.list; \ 121 | _update_repo() { \ 122 | dpkg-scanpackages . > Packages; \ 123 | # work around the following APT issue by using "Acquire::GzipIndexes=false" (overriding "/etc/apt/apt.conf.d/docker-gzip-indexes") 124 | # Could not open file /var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages - open (13: Permission denied) 125 | # ... 126 | # E: Failed to fetch store:/var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages Could not open file /var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages - open (13: Permission denied) 127 | apt-get -o Acquire::GzipIndexes=false update; \ 128 | }; \ 129 | _update_repo; \ 130 | \ 131 | # build .deb files from upstream's source packages (which are verified by apt-get) 132 | nproc="$(nproc)"; \ 133 | export DEB_BUILD_OPTIONS="nocheck parallel=$nproc"; \ 134 | # we have to build postgresql-common-dev first because postgresql-$PG_MAJOR shares "debian/rules" logic with it: https://salsa.debian.org/postgresql/postgresql/-/commit/f4338a0d28cf4541956bddb0f4e444ba9dba81b9 135 | apt-get build-dep -y postgresql-common-dev; \ 136 | apt-get source --compile postgresql-common-dev; \ 137 | _update_repo; \ 138 | apt-get build-dep -y "postgresql-$PG_MAJOR=$PG_VERSION"; \ 139 | apt-get source --compile "postgresql-$PG_MAJOR=$PG_VERSION"; \ 140 | \ 141 | # we don't remove APT lists here because they get re-downloaded and removed later 142 | \ 143 | # reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies 144 | # (which is done after we install the built packages so we don't have to redownload any overlapping dependencies) 145 | apt-mark showmanual | xargs apt-mark auto > /dev/null; \ 146 | apt-mark manual $savedAptMark; \ 147 | \ 148 | ls -lAFh; \ 149 | _update_repo; \ 150 | grep '^Package: ' Packages; \ 151 | cd /; \ 152 | ;; \ 153 | esac; \ 154 | \ 155 | apt-get install -y --no-install-recommends postgresql-common; \ 156 | sed -ri 's/#(create_main_cluster) .*$/\1 = false/' /etc/postgresql-common/createcluster.conf; \ 157 | apt-get install -y --no-install-recommends \ 158 | "postgresql-$PG_MAJOR=$PG_VERSION" \ 159 | ; \ 160 | \ 161 | rm -rf /var/lib/apt/lists/*; \ 162 | \ 163 | if [ -n "$tempDir" ]; then \ 164 | # if we have leftovers from building, let's purge them (including extra, unnecessary build deps) 165 | apt-get purge -y --auto-remove; \ 166 | rm -rf "$tempDir" /etc/apt/sources.list.d/temp.list; \ 167 | fi; \ 168 | \ 169 | # some of the steps above generate a lot of "*.pyc" files (and setting "PYTHONDONTWRITEBYTECODE" beforehand doesn't propagate properly for some reason), so we clean them up manually (as long as they aren't owned by a package) 170 | find /usr -name '*.pyc' -type f -exec bash -c 'for pyc; do dpkg -S "$pyc" &> /dev/null || rm -vf "$pyc"; done' -- '{}' +; \ 171 | \ 172 | postgres --version 173 | 174 | # make the sample config easier to munge (and "correct by default") 175 | RUN set -eux; \ 176 | dpkg-divert --add --rename --divert "/usr/share/postgresql/postgresql.conf.sample.dpkg" "/usr/share/postgresql/$PG_MAJOR/postgresql.conf.sample"; \ 177 | cp -v /usr/share/postgresql/postgresql.conf.sample.dpkg /usr/share/postgresql/postgresql.conf.sample; \ 178 | ln -sv ../postgresql.conf.sample "/usr/share/postgresql/$PG_MAJOR/"; \ 179 | sed -ri "s!^#?(listen_addresses)\s*=\s*\S+.*!\1 = '*'!" /usr/share/postgresql/postgresql.conf.sample; \ 180 | grep -F "listen_addresses = '*'" /usr/share/postgresql/postgresql.conf.sample 181 | 182 | RUN install --verbose --directory --owner postgres --group postgres --mode 3777 /var/run/postgresql 183 | 184 | ENV PGDATA /var/lib/postgresql/data 185 | # this 1777 will be replaced by 0700 at runtime (allows semi-arbitrary "--user" values) 186 | RUN install --verbose --directory --owner postgres --group postgres --mode 1777 "$PGDATA" 187 | VOLUME /var/lib/postgresql/data 188 | 189 | COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ 190 | RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh 191 | ENTRYPOINT ["docker-entrypoint.sh"] 192 | 193 | # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL 194 | # calls "Fast Shutdown mode" wherein new connections are disallowed and any 195 | # in-progress transactions are aborted, allowing PostgreSQL to stop cleanly and 196 | # flush tables to disk. 197 | # 198 | # See https://www.postgresql.org/docs/current/server-shutdown.html for more details 199 | # about available PostgreSQL server shutdown signals. 200 | # 201 | # See also https://www.postgresql.org/docs/current/server-start.html for further 202 | # justification of this as the default value, namely that the example (and 203 | # shipped) systemd service files use the "Fast Shutdown mode" for service 204 | # termination. 205 | # 206 | STOPSIGNAL SIGINT 207 | # 208 | # An additional setting that is recommended for all users regardless of this 209 | # value is the runtime "--stop-timeout" (or your orchestrator/runtime's 210 | # equivalent) for controlling how long to wait between sending the defined 211 | # STOPSIGNAL and sending SIGKILL. 212 | # 213 | # The default in most runtimes (such as Docker) is 10 seconds, and the 214 | # documentation at https://www.postgresql.org/docs/current/server-start.html notes 215 | # that even 90 seconds may not be long enough in many instances. 216 | 217 | EXPOSE 5432 218 | CMD ["postgres"] 219 | -------------------------------------------------------------------------------- /14/bookworm/docker-ensure-initdb.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | # 5 | # This script is intended for three main use cases: 6 | # 7 | # 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior 8 | # 9 | # 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution 10 | # (no-op if database is already initialized) 11 | # 12 | # 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use 13 | # (error if database is already initialized) 14 | # 15 | 16 | source /usr/local/bin/docker-entrypoint.sh 17 | 18 | # arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) 19 | if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then 20 | set -- postgres "$@" 21 | fi 22 | 23 | # see also "_main" in "docker-entrypoint.sh" 24 | 25 | docker_setup_env 26 | # setup data directories and permissions (when run as root) 27 | docker_create_db_directories 28 | if [ "$(id -u)" = '0' ]; then 29 | # then restart script as postgres user 30 | exec gosu postgres "$BASH_SOURCE" "$@" 31 | fi 32 | 33 | # only run initialization on an empty data directory 34 | if [ -z "$DATABASE_ALREADY_EXISTS" ]; then 35 | docker_verify_minimum_env 36 | 37 | # check dir permissions to reduce likelihood of half-initialized database 38 | ls /docker-entrypoint-initdb.d/ > /dev/null 39 | 40 | docker_init_database_dir 41 | pg_setup_hba_conf "$@" 42 | 43 | # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless 44 | # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS 45 | export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" 46 | docker_temp_server_start "$@" 47 | 48 | docker_setup_db 49 | docker_process_init_files /docker-entrypoint-initdb.d/* 50 | 51 | docker_temp_server_stop 52 | unset PGPASSWORD 53 | else 54 | self="$(basename "$0")" 55 | case "$self" in 56 | docker-ensure-initdb.sh) 57 | echo >&2 "$self: note: database already initialized in '$PGDATA'!" 58 | exit 0 59 | ;; 60 | 61 | docker-enforce-initdb.sh) 62 | echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" 63 | exit 1 64 | ;; 65 | 66 | *) 67 | echo >&2 "$self: error: unknown file name: $self" 68 | exit 99 69 | ;; 70 | esac 71 | fi 72 | -------------------------------------------------------------------------------- /14/bullseye/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" 3 | # 4 | # PLEASE DO NOT EDIT IT DIRECTLY. 5 | # 6 | 7 | FROM debian:bullseye-slim 8 | 9 | # explicitly set user/group IDs 10 | RUN set -eux; \ 11 | groupadd -r postgres --gid=999; \ 12 | # https://salsa.debian.org/postgresql/postgresql-common/blob/997d842ee744687d99a2b2d95c1083a2615c79e8/debian/postgresql-common.postinst#L32-35 13 | useradd -r -g postgres --uid=999 --home-dir=/var/lib/postgresql --shell=/bin/bash postgres; \ 14 | # also create the postgres user's home directory with appropriate permissions 15 | # see https://github.com/docker-library/postgres/issues/274 16 | install --verbose --directory --owner postgres --group postgres --mode 1777 /var/lib/postgresql 17 | 18 | RUN set -ex; \ 19 | apt-get update; \ 20 | apt-get install -y --no-install-recommends \ 21 | gnupg \ 22 | # https://www.postgresql.org/docs/16/app-psql.html#APP-PSQL-META-COMMAND-PSET-PAGER 23 | # https://github.com/postgres/postgres/blob/REL_16_1/src/include/fe_utils/print.h#L25 24 | # (if "less" is available, it gets used as the default pager for psql, and it only adds ~1.5MiB to our image size) 25 | less \ 26 | ; \ 27 | rm -rf /var/lib/apt/lists/* 28 | 29 | # grab gosu for easy step-down from root 30 | # https://github.com/tianon/gosu/releases 31 | ENV GOSU_VERSION 1.17 32 | RUN set -eux; \ 33 | savedAptMark="$(apt-mark showmanual)"; \ 34 | apt-get update; \ 35 | apt-get install -y --no-install-recommends ca-certificates wget; \ 36 | rm -rf /var/lib/apt/lists/*; \ 37 | dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \ 38 | wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \ 39 | wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \ 40 | export GNUPGHOME="$(mktemp -d)"; \ 41 | gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ 42 | gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \ 43 | gpgconf --kill all; \ 44 | rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \ 45 | apt-mark auto '.*' > /dev/null; \ 46 | [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; \ 47 | apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ 48 | chmod +x /usr/local/bin/gosu; \ 49 | gosu --version; \ 50 | gosu nobody true 51 | 52 | # make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default 53 | RUN set -eux; \ 54 | if [ -f /etc/dpkg/dpkg.cfg.d/docker ]; then \ 55 | # if this file exists, we're likely in "debian:xxx-slim", and locales are thus being excluded so we need to remove that exclusion (since we need locales) 56 | grep -q '/usr/share/locale' /etc/dpkg/dpkg.cfg.d/docker; \ 57 | sed -ri '/\/usr\/share\/locale/d' /etc/dpkg/dpkg.cfg.d/docker; \ 58 | ! grep -q '/usr/share/locale' /etc/dpkg/dpkg.cfg.d/docker; \ 59 | fi; \ 60 | apt-get update; apt-get install -y --no-install-recommends locales; rm -rf /var/lib/apt/lists/*; \ 61 | echo 'en_US.UTF-8 UTF-8' >> /etc/locale.gen; \ 62 | locale-gen; \ 63 | locale -a | grep 'en_US.utf8' 64 | ENV LANG en_US.utf8 65 | 66 | RUN set -eux; \ 67 | apt-get update; \ 68 | apt-get install -y --no-install-recommends \ 69 | libnss-wrapper \ 70 | xz-utils \ 71 | zstd \ 72 | ; \ 73 | rm -rf /var/lib/apt/lists/* 74 | 75 | RUN mkdir /docker-entrypoint-initdb.d 76 | 77 | RUN set -ex; \ 78 | # pub 4096R/ACCC4CF8 2011-10-13 [expires: 2019-07-02] 79 | # Key fingerprint = B97B 0AFC AA1A 47F0 44F2 44A0 7FCC 7D46 ACCC 4CF8 80 | # uid PostgreSQL Debian Repository 81 | key='B97B0AFCAA1A47F044F244A07FCC7D46ACCC4CF8'; \ 82 | export GNUPGHOME="$(mktemp -d)"; \ 83 | mkdir -p /usr/local/share/keyrings/; \ 84 | gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \ 85 | gpg --batch --export --armor "$key" > /usr/local/share/keyrings/postgres.gpg.asc; \ 86 | gpgconf --kill all; \ 87 | rm -rf "$GNUPGHOME" 88 | 89 | ENV PG_MAJOR 14 90 | ENV PATH $PATH:/usr/lib/postgresql/$PG_MAJOR/bin 91 | 92 | ENV PG_VERSION 14.18-1.pgdg110+1 93 | 94 | RUN set -ex; \ 95 | \ 96 | # see note below about "*.pyc" files 97 | export PYTHONDONTWRITEBYTECODE=1; \ 98 | \ 99 | dpkgArch="$(dpkg --print-architecture)"; \ 100 | aptRepo="[ signed-by=/usr/local/share/keyrings/postgres.gpg.asc ] http://apt.postgresql.org/pub/repos/apt/ bullseye-pgdg main $PG_MAJOR"; \ 101 | case "$dpkgArch" in \ 102 | amd64 | arm64 | ppc64el) \ 103 | # arches officialy built by upstream 104 | echo "deb $aptRepo" > /etc/apt/sources.list.d/pgdg.list; \ 105 | apt-get update; \ 106 | ;; \ 107 | *) \ 108 | # we're on an architecture upstream doesn't officially build for 109 | # let's build binaries from their published source packages 110 | echo "deb-src $aptRepo" > /etc/apt/sources.list.d/pgdg.list; \ 111 | \ 112 | savedAptMark="$(apt-mark showmanual)"; \ 113 | \ 114 | tempDir="$(mktemp -d)"; \ 115 | cd "$tempDir"; \ 116 | \ 117 | # create a temporary local APT repo to install from (so that dependency resolution can be handled by APT, as it should be) 118 | apt-get update; \ 119 | apt-get install -y --no-install-recommends dpkg-dev; \ 120 | echo "deb [ trusted=yes ] file://$tempDir ./" > /etc/apt/sources.list.d/temp.list; \ 121 | _update_repo() { \ 122 | dpkg-scanpackages . > Packages; \ 123 | # work around the following APT issue by using "Acquire::GzipIndexes=false" (overriding "/etc/apt/apt.conf.d/docker-gzip-indexes") 124 | # Could not open file /var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages - open (13: Permission denied) 125 | # ... 126 | # E: Failed to fetch store:/var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages Could not open file /var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages - open (13: Permission denied) 127 | apt-get -o Acquire::GzipIndexes=false update; \ 128 | }; \ 129 | _update_repo; \ 130 | \ 131 | # build .deb files from upstream's source packages (which are verified by apt-get) 132 | nproc="$(nproc)"; \ 133 | export DEB_BUILD_OPTIONS="nocheck parallel=$nproc"; \ 134 | # we have to build postgresql-common-dev first because postgresql-$PG_MAJOR shares "debian/rules" logic with it: https://salsa.debian.org/postgresql/postgresql/-/commit/f4338a0d28cf4541956bddb0f4e444ba9dba81b9 135 | apt-get build-dep -y postgresql-common-dev; \ 136 | apt-get source --compile postgresql-common-dev; \ 137 | _update_repo; \ 138 | apt-get build-dep -y "postgresql-$PG_MAJOR=$PG_VERSION"; \ 139 | apt-get source --compile "postgresql-$PG_MAJOR=$PG_VERSION"; \ 140 | \ 141 | # we don't remove APT lists here because they get re-downloaded and removed later 142 | \ 143 | # reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies 144 | # (which is done after we install the built packages so we don't have to redownload any overlapping dependencies) 145 | apt-mark showmanual | xargs apt-mark auto > /dev/null; \ 146 | apt-mark manual $savedAptMark; \ 147 | \ 148 | ls -lAFh; \ 149 | _update_repo; \ 150 | grep '^Package: ' Packages; \ 151 | cd /; \ 152 | ;; \ 153 | esac; \ 154 | \ 155 | apt-get install -y --no-install-recommends postgresql-common; \ 156 | sed -ri 's/#(create_main_cluster) .*$/\1 = false/' /etc/postgresql-common/createcluster.conf; \ 157 | apt-get install -y --no-install-recommends \ 158 | "postgresql-$PG_MAJOR=$PG_VERSION" \ 159 | ; \ 160 | \ 161 | rm -rf /var/lib/apt/lists/*; \ 162 | \ 163 | if [ -n "$tempDir" ]; then \ 164 | # if we have leftovers from building, let's purge them (including extra, unnecessary build deps) 165 | apt-get purge -y --auto-remove; \ 166 | rm -rf "$tempDir" /etc/apt/sources.list.d/temp.list; \ 167 | fi; \ 168 | \ 169 | # some of the steps above generate a lot of "*.pyc" files (and setting "PYTHONDONTWRITEBYTECODE" beforehand doesn't propagate properly for some reason), so we clean them up manually (as long as they aren't owned by a package) 170 | find /usr -name '*.pyc' -type f -exec bash -c 'for pyc; do dpkg -S "$pyc" &> /dev/null || rm -vf "$pyc"; done' -- '{}' +; \ 171 | \ 172 | postgres --version 173 | 174 | # make the sample config easier to munge (and "correct by default") 175 | RUN set -eux; \ 176 | dpkg-divert --add --rename --divert "/usr/share/postgresql/postgresql.conf.sample.dpkg" "/usr/share/postgresql/$PG_MAJOR/postgresql.conf.sample"; \ 177 | cp -v /usr/share/postgresql/postgresql.conf.sample.dpkg /usr/share/postgresql/postgresql.conf.sample; \ 178 | ln -sv ../postgresql.conf.sample "/usr/share/postgresql/$PG_MAJOR/"; \ 179 | sed -ri "s!^#?(listen_addresses)\s*=\s*\S+.*!\1 = '*'!" /usr/share/postgresql/postgresql.conf.sample; \ 180 | grep -F "listen_addresses = '*'" /usr/share/postgresql/postgresql.conf.sample 181 | 182 | RUN install --verbose --directory --owner postgres --group postgres --mode 3777 /var/run/postgresql 183 | 184 | ENV PGDATA /var/lib/postgresql/data 185 | # this 1777 will be replaced by 0700 at runtime (allows semi-arbitrary "--user" values) 186 | RUN install --verbose --directory --owner postgres --group postgres --mode 1777 "$PGDATA" 187 | VOLUME /var/lib/postgresql/data 188 | 189 | COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ 190 | RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh 191 | ENTRYPOINT ["docker-entrypoint.sh"] 192 | 193 | # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL 194 | # calls "Fast Shutdown mode" wherein new connections are disallowed and any 195 | # in-progress transactions are aborted, allowing PostgreSQL to stop cleanly and 196 | # flush tables to disk. 197 | # 198 | # See https://www.postgresql.org/docs/current/server-shutdown.html for more details 199 | # about available PostgreSQL server shutdown signals. 200 | # 201 | # See also https://www.postgresql.org/docs/current/server-start.html for further 202 | # justification of this as the default value, namely that the example (and 203 | # shipped) systemd service files use the "Fast Shutdown mode" for service 204 | # termination. 205 | # 206 | STOPSIGNAL SIGINT 207 | # 208 | # An additional setting that is recommended for all users regardless of this 209 | # value is the runtime "--stop-timeout" (or your orchestrator/runtime's 210 | # equivalent) for controlling how long to wait between sending the defined 211 | # STOPSIGNAL and sending SIGKILL. 212 | # 213 | # The default in most runtimes (such as Docker) is 10 seconds, and the 214 | # documentation at https://www.postgresql.org/docs/current/server-start.html notes 215 | # that even 90 seconds may not be long enough in many instances. 216 | 217 | EXPOSE 5432 218 | CMD ["postgres"] 219 | -------------------------------------------------------------------------------- /14/bullseye/docker-ensure-initdb.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | # 5 | # This script is intended for three main use cases: 6 | # 7 | # 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior 8 | # 9 | # 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution 10 | # (no-op if database is already initialized) 11 | # 12 | # 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use 13 | # (error if database is already initialized) 14 | # 15 | 16 | source /usr/local/bin/docker-entrypoint.sh 17 | 18 | # arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) 19 | if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then 20 | set -- postgres "$@" 21 | fi 22 | 23 | # see also "_main" in "docker-entrypoint.sh" 24 | 25 | docker_setup_env 26 | # setup data directories and permissions (when run as root) 27 | docker_create_db_directories 28 | if [ "$(id -u)" = '0' ]; then 29 | # then restart script as postgres user 30 | exec gosu postgres "$BASH_SOURCE" "$@" 31 | fi 32 | 33 | # only run initialization on an empty data directory 34 | if [ -z "$DATABASE_ALREADY_EXISTS" ]; then 35 | docker_verify_minimum_env 36 | 37 | # check dir permissions to reduce likelihood of half-initialized database 38 | ls /docker-entrypoint-initdb.d/ > /dev/null 39 | 40 | docker_init_database_dir 41 | pg_setup_hba_conf "$@" 42 | 43 | # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless 44 | # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS 45 | export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" 46 | docker_temp_server_start "$@" 47 | 48 | docker_setup_db 49 | docker_process_init_files /docker-entrypoint-initdb.d/* 50 | 51 | docker_temp_server_stop 52 | unset PGPASSWORD 53 | else 54 | self="$(basename "$0")" 55 | case "$self" in 56 | docker-ensure-initdb.sh) 57 | echo >&2 "$self: note: database already initialized in '$PGDATA'!" 58 | exit 0 59 | ;; 60 | 61 | docker-enforce-initdb.sh) 62 | echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" 63 | exit 1 64 | ;; 65 | 66 | *) 67 | echo >&2 "$self: error: unknown file name: $self" 68 | exit 99 69 | ;; 70 | esac 71 | fi 72 | -------------------------------------------------------------------------------- /15/alpine3.21/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" 3 | # 4 | # PLEASE DO NOT EDIT IT DIRECTLY. 5 | # 6 | 7 | FROM alpine:3.21 8 | 9 | # 70 is the standard uid/gid for "postgres" in Alpine 10 | # https://git.alpinelinux.org/aports/tree/main/postgresql-common/postgresql-common.pre-install?h=3.22-stable 11 | RUN set -eux; \ 12 | addgroup -g 70 -S postgres; \ 13 | adduser -u 70 -S -D -G postgres -H -h /var/lib/postgresql -s /bin/sh postgres; \ 14 | # also create the postgres user's home directory with appropriate permissions 15 | # see https://github.com/docker-library/postgres/issues/274 16 | install --verbose --directory --owner postgres --group postgres --mode 1777 /var/lib/postgresql 17 | 18 | # grab gosu for easy step-down from root 19 | # https://github.com/tianon/gosu/releases 20 | ENV GOSU_VERSION 1.17 21 | RUN set -eux; \ 22 | \ 23 | apk add --no-cache --virtual .gosu-deps \ 24 | ca-certificates \ 25 | dpkg \ 26 | gnupg \ 27 | ; \ 28 | \ 29 | dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \ 30 | wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \ 31 | wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \ 32 | \ 33 | # verify the signature 34 | export GNUPGHOME="$(mktemp -d)"; \ 35 | gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ 36 | gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \ 37 | gpgconf --kill all; \ 38 | rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \ 39 | \ 40 | # clean up fetch dependencies 41 | apk del --no-network .gosu-deps; \ 42 | \ 43 | chmod +x /usr/local/bin/gosu; \ 44 | # verify that the binary works 45 | gosu --version; \ 46 | gosu nobody true 47 | RUN set -eux; ln -svf gosu /usr/local/bin/su-exec; su-exec nobody true # backwards compatibility (removed in PostgreSQL 17+) 48 | 49 | # make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default 50 | # alpine doesn't require explicit locale-file generation 51 | ENV LANG en_US.utf8 52 | 53 | RUN mkdir /docker-entrypoint-initdb.d 54 | 55 | ENV PG_MAJOR 15 56 | ENV PG_VERSION 15.13 57 | ENV PG_SHA256 4f62e133d22ea08a0401b0840920e26698644d01a80c34341fb732dd0a90ca5d 58 | 59 | ENV DOCKER_PG_LLVM_DEPS \ 60 | llvm19-dev \ 61 | clang19 62 | 63 | RUN set -eux; \ 64 | \ 65 | wget -O postgresql.tar.bz2 "https://ftp.postgresql.org/pub/source/v$PG_VERSION/postgresql-$PG_VERSION.tar.bz2"; \ 66 | echo "$PG_SHA256 *postgresql.tar.bz2" | sha256sum -c -; \ 67 | mkdir -p /usr/src/postgresql; \ 68 | tar \ 69 | --extract \ 70 | --file postgresql.tar.bz2 \ 71 | --directory /usr/src/postgresql \ 72 | --strip-components 1 \ 73 | ; \ 74 | rm postgresql.tar.bz2; \ 75 | \ 76 | apk add --no-cache --virtual .build-deps \ 77 | $DOCKER_PG_LLVM_DEPS \ 78 | bison \ 79 | coreutils \ 80 | dpkg-dev dpkg \ 81 | flex \ 82 | g++ \ 83 | gcc \ 84 | krb5-dev \ 85 | libc-dev \ 86 | libedit-dev \ 87 | libxml2-dev \ 88 | libxslt-dev \ 89 | linux-headers \ 90 | make \ 91 | openldap-dev \ 92 | openssl-dev \ 93 | perl-dev \ 94 | perl-ipc-run \ 95 | perl-utils \ 96 | python3-dev \ 97 | tcl-dev \ 98 | util-linux-dev \ 99 | zlib-dev \ 100 | # https://www.postgresql.org/docs/10/static/release-10.html#id-1.11.6.9.5.13 101 | icu-dev \ 102 | # https://www.postgresql.org/docs/14/release-14.html#id-1.11.6.5.5.3.7 103 | lz4-dev \ 104 | # https://www.postgresql.org/docs/15/release-15.html "--with-zstd to enable Zstandard builds" 105 | zstd-dev \ 106 | ; \ 107 | \ 108 | cd /usr/src/postgresql; \ 109 | # update "DEFAULT_PGSOCKET_DIR" to "/var/run/postgresql" (matching Debian) 110 | # see https://anonscm.debian.org/git/pkg-postgresql/postgresql.git/tree/debian/patches/51-default-sockets-in-var.patch?id=8b539fcb3e093a521c095e70bdfa76887217b89f 111 | awk '$1 == "#define" && $2 == "DEFAULT_PGSOCKET_DIR" && $3 == "\"/tmp\"" { $3 = "\"/var/run/postgresql\""; print; next } { print }' src/include/pg_config_manual.h > src/include/pg_config_manual.h.new; \ 112 | grep '/var/run/postgresql' src/include/pg_config_manual.h.new; \ 113 | mv src/include/pg_config_manual.h.new src/include/pg_config_manual.h; \ 114 | gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \ 115 | \ 116 | # https://git.alpinelinux.org/aports/tree/community/postgresql15/APKBUILD?h=3.22-stable#n176 ("export LLVM_CONFIG") 117 | export LLVM_CONFIG="/usr/lib/llvm19/bin/llvm-config"; \ 118 | # https://git.alpinelinux.org/aports/tree/community/postgresql15/APKBUILD?h=3.22-stable#n180 ("older clang versions don't have a 'clang' exe anymore.") 119 | export CLANG=clang-19; \ 120 | \ 121 | # configure options taken from: 122 | # https://anonscm.debian.org/cgit/pkg-postgresql/postgresql.git/tree/debian/rules?h=9.5 123 | ./configure \ 124 | --enable-option-checking=fatal \ 125 | --build="$gnuArch" \ 126 | # "/usr/src/postgresql/src/backend/access/common/tupconvert.c:105: undefined reference to `libintl_gettext'" 127 | # --enable-nls \ 128 | --enable-integer-datetimes \ 129 | --enable-thread-safety \ 130 | --enable-tap-tests \ 131 | # skip debugging info -- we want tiny size instead 132 | # --enable-debug \ 133 | --disable-rpath \ 134 | --with-uuid=e2fs \ 135 | --with-gnu-ld \ 136 | --with-pgport=5432 \ 137 | --with-system-tzdata=/usr/share/zoneinfo \ 138 | --prefix=/usr/local \ 139 | --with-includes=/usr/local/include \ 140 | --with-libraries=/usr/local/lib \ 141 | --with-gssapi \ 142 | --with-ldap \ 143 | --with-tcl \ 144 | --with-perl \ 145 | --with-python \ 146 | # --with-pam \ 147 | --with-openssl \ 148 | --with-libxml \ 149 | --with-libxslt \ 150 | --with-icu \ 151 | --with-llvm \ 152 | --with-lz4 \ 153 | --with-zstd \ 154 | ; \ 155 | make -j "$(nproc)" world-bin; \ 156 | make install-world-bin; \ 157 | make -C contrib install; \ 158 | \ 159 | runDeps="$( \ 160 | scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \ 161 | | tr ',' '\n' \ 162 | | sort -u \ 163 | | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ 164 | # Remove plperl, plpython and pltcl dependencies by default to save image size 165 | # To use the pl extensions, those have to be installed in a derived image 166 | | grep -v -e perl -e python -e tcl \ 167 | )"; \ 168 | apk add --no-cache --virtual .postgresql-rundeps \ 169 | $runDeps \ 170 | bash \ 171 | tzdata \ 172 | zstd \ 173 | # https://wiki.alpinelinux.org/wiki/Release_Notes_for_Alpine_3.16.0#ICU_data_split 174 | icu-data-full \ 175 | # https://git.alpinelinux.org/aports/tree/community/nss_wrapper/APKBUILD?h=3.22-stable#n7 ("ppc64le: test case segfaults") 176 | $([ "$(apk --print-arch)" != 'ppc64le' ] && echo 'nss_wrapper') \ 177 | ; \ 178 | apk del --no-network .build-deps; \ 179 | cd /; \ 180 | rm -rf \ 181 | /usr/src/postgresql \ 182 | /usr/local/share/doc \ 183 | /usr/local/share/man \ 184 | ; \ 185 | \ 186 | postgres --version 187 | 188 | # make the sample config easier to munge (and "correct by default") 189 | RUN set -eux; \ 190 | cp -v /usr/local/share/postgresql/postgresql.conf.sample /usr/local/share/postgresql/postgresql.conf.sample.orig; \ 191 | sed -ri "s!^#?(listen_addresses)\s*=\s*\S+.*!\1 = '*'!" /usr/local/share/postgresql/postgresql.conf.sample; \ 192 | grep -F "listen_addresses = '*'" /usr/local/share/postgresql/postgresql.conf.sample 193 | 194 | RUN install --verbose --directory --owner postgres --group postgres --mode 3777 /var/run/postgresql 195 | 196 | ENV PGDATA /var/lib/postgresql/data 197 | # this 1777 will be replaced by 0700 at runtime (allows semi-arbitrary "--user" values) 198 | RUN install --verbose --directory --owner postgres --group postgres --mode 1777 "$PGDATA" 199 | VOLUME /var/lib/postgresql/data 200 | 201 | COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ 202 | RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh 203 | ENTRYPOINT ["docker-entrypoint.sh"] 204 | 205 | # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL 206 | # calls "Fast Shutdown mode" wherein new connections are disallowed and any 207 | # in-progress transactions are aborted, allowing PostgreSQL to stop cleanly and 208 | # flush tables to disk. 209 | # 210 | # See https://www.postgresql.org/docs/current/server-shutdown.html for more details 211 | # about available PostgreSQL server shutdown signals. 212 | # 213 | # See also https://www.postgresql.org/docs/current/server-start.html for further 214 | # justification of this as the default value, namely that the example (and 215 | # shipped) systemd service files use the "Fast Shutdown mode" for service 216 | # termination. 217 | # 218 | STOPSIGNAL SIGINT 219 | # 220 | # An additional setting that is recommended for all users regardless of this 221 | # value is the runtime "--stop-timeout" (or your orchestrator/runtime's 222 | # equivalent) for controlling how long to wait between sending the defined 223 | # STOPSIGNAL and sending SIGKILL. 224 | # 225 | # The default in most runtimes (such as Docker) is 10 seconds, and the 226 | # documentation at https://www.postgresql.org/docs/current/server-start.html notes 227 | # that even 90 seconds may not be long enough in many instances. 228 | 229 | EXPOSE 5432 230 | CMD ["postgres"] 231 | -------------------------------------------------------------------------------- /15/alpine3.21/docker-ensure-initdb.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | # 5 | # This script is intended for three main use cases: 6 | # 7 | # 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior 8 | # 9 | # 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution 10 | # (no-op if database is already initialized) 11 | # 12 | # 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use 13 | # (error if database is already initialized) 14 | # 15 | 16 | source /usr/local/bin/docker-entrypoint.sh 17 | 18 | # arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) 19 | if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then 20 | set -- postgres "$@" 21 | fi 22 | 23 | # see also "_main" in "docker-entrypoint.sh" 24 | 25 | docker_setup_env 26 | # setup data directories and permissions (when run as root) 27 | docker_create_db_directories 28 | if [ "$(id -u)" = '0' ]; then 29 | # then restart script as postgres user 30 | exec gosu postgres "$BASH_SOURCE" "$@" 31 | fi 32 | 33 | # only run initialization on an empty data directory 34 | if [ -z "$DATABASE_ALREADY_EXISTS" ]; then 35 | docker_verify_minimum_env 36 | 37 | # check dir permissions to reduce likelihood of half-initialized database 38 | ls /docker-entrypoint-initdb.d/ > /dev/null 39 | 40 | docker_init_database_dir 41 | pg_setup_hba_conf "$@" 42 | 43 | # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless 44 | # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS 45 | export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" 46 | docker_temp_server_start "$@" 47 | 48 | docker_setup_db 49 | docker_process_init_files /docker-entrypoint-initdb.d/* 50 | 51 | docker_temp_server_stop 52 | unset PGPASSWORD 53 | else 54 | self="$(basename "$0")" 55 | case "$self" in 56 | docker-ensure-initdb.sh) 57 | echo >&2 "$self: note: database already initialized in '$PGDATA'!" 58 | exit 0 59 | ;; 60 | 61 | docker-enforce-initdb.sh) 62 | echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" 63 | exit 1 64 | ;; 65 | 66 | *) 67 | echo >&2 "$self: error: unknown file name: $self" 68 | exit 99 69 | ;; 70 | esac 71 | fi 72 | -------------------------------------------------------------------------------- /15/alpine3.22/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" 3 | # 4 | # PLEASE DO NOT EDIT IT DIRECTLY. 5 | # 6 | 7 | FROM alpine:3.22 8 | 9 | # 70 is the standard uid/gid for "postgres" in Alpine 10 | # https://git.alpinelinux.org/aports/tree/main/postgresql-common/postgresql-common.pre-install?h=3.22-stable 11 | RUN set -eux; \ 12 | addgroup -g 70 -S postgres; \ 13 | adduser -u 70 -S -D -G postgres -H -h /var/lib/postgresql -s /bin/sh postgres; \ 14 | # also create the postgres user's home directory with appropriate permissions 15 | # see https://github.com/docker-library/postgres/issues/274 16 | install --verbose --directory --owner postgres --group postgres --mode 1777 /var/lib/postgresql 17 | 18 | # grab gosu for easy step-down from root 19 | # https://github.com/tianon/gosu/releases 20 | ENV GOSU_VERSION 1.17 21 | RUN set -eux; \ 22 | \ 23 | apk add --no-cache --virtual .gosu-deps \ 24 | ca-certificates \ 25 | dpkg \ 26 | gnupg \ 27 | ; \ 28 | \ 29 | dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \ 30 | wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \ 31 | wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \ 32 | \ 33 | # verify the signature 34 | export GNUPGHOME="$(mktemp -d)"; \ 35 | gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ 36 | gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \ 37 | gpgconf --kill all; \ 38 | rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \ 39 | \ 40 | # clean up fetch dependencies 41 | apk del --no-network .gosu-deps; \ 42 | \ 43 | chmod +x /usr/local/bin/gosu; \ 44 | # verify that the binary works 45 | gosu --version; \ 46 | gosu nobody true 47 | RUN set -eux; ln -svf gosu /usr/local/bin/su-exec; su-exec nobody true # backwards compatibility (removed in PostgreSQL 17+) 48 | 49 | # make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default 50 | # alpine doesn't require explicit locale-file generation 51 | ENV LANG en_US.utf8 52 | 53 | RUN mkdir /docker-entrypoint-initdb.d 54 | 55 | ENV PG_MAJOR 15 56 | ENV PG_VERSION 15.13 57 | ENV PG_SHA256 4f62e133d22ea08a0401b0840920e26698644d01a80c34341fb732dd0a90ca5d 58 | 59 | ENV DOCKER_PG_LLVM_DEPS \ 60 | llvm19-dev \ 61 | clang19 62 | 63 | RUN set -eux; \ 64 | \ 65 | wget -O postgresql.tar.bz2 "https://ftp.postgresql.org/pub/source/v$PG_VERSION/postgresql-$PG_VERSION.tar.bz2"; \ 66 | echo "$PG_SHA256 *postgresql.tar.bz2" | sha256sum -c -; \ 67 | mkdir -p /usr/src/postgresql; \ 68 | tar \ 69 | --extract \ 70 | --file postgresql.tar.bz2 \ 71 | --directory /usr/src/postgresql \ 72 | --strip-components 1 \ 73 | ; \ 74 | rm postgresql.tar.bz2; \ 75 | \ 76 | apk add --no-cache --virtual .build-deps \ 77 | $DOCKER_PG_LLVM_DEPS \ 78 | bison \ 79 | coreutils \ 80 | dpkg-dev dpkg \ 81 | flex \ 82 | g++ \ 83 | gcc \ 84 | krb5-dev \ 85 | libc-dev \ 86 | libedit-dev \ 87 | libxml2-dev \ 88 | libxslt-dev \ 89 | linux-headers \ 90 | make \ 91 | openldap-dev \ 92 | openssl-dev \ 93 | perl-dev \ 94 | perl-ipc-run \ 95 | perl-utils \ 96 | python3-dev \ 97 | tcl-dev \ 98 | util-linux-dev \ 99 | zlib-dev \ 100 | # https://www.postgresql.org/docs/10/static/release-10.html#id-1.11.6.9.5.13 101 | icu-dev \ 102 | # https://www.postgresql.org/docs/14/release-14.html#id-1.11.6.5.5.3.7 103 | lz4-dev \ 104 | # https://www.postgresql.org/docs/15/release-15.html "--with-zstd to enable Zstandard builds" 105 | zstd-dev \ 106 | ; \ 107 | \ 108 | cd /usr/src/postgresql; \ 109 | # update "DEFAULT_PGSOCKET_DIR" to "/var/run/postgresql" (matching Debian) 110 | # see https://anonscm.debian.org/git/pkg-postgresql/postgresql.git/tree/debian/patches/51-default-sockets-in-var.patch?id=8b539fcb3e093a521c095e70bdfa76887217b89f 111 | awk '$1 == "#define" && $2 == "DEFAULT_PGSOCKET_DIR" && $3 == "\"/tmp\"" { $3 = "\"/var/run/postgresql\""; print; next } { print }' src/include/pg_config_manual.h > src/include/pg_config_manual.h.new; \ 112 | grep '/var/run/postgresql' src/include/pg_config_manual.h.new; \ 113 | mv src/include/pg_config_manual.h.new src/include/pg_config_manual.h; \ 114 | gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \ 115 | \ 116 | # https://git.alpinelinux.org/aports/tree/community/postgresql15/APKBUILD?h=3.22-stable#n176 ("export LLVM_CONFIG") 117 | export LLVM_CONFIG="/usr/lib/llvm19/bin/llvm-config"; \ 118 | # https://git.alpinelinux.org/aports/tree/community/postgresql15/APKBUILD?h=3.22-stable#n180 ("older clang versions don't have a 'clang' exe anymore.") 119 | export CLANG=clang-19; \ 120 | \ 121 | # configure options taken from: 122 | # https://anonscm.debian.org/cgit/pkg-postgresql/postgresql.git/tree/debian/rules?h=9.5 123 | ./configure \ 124 | --enable-option-checking=fatal \ 125 | --build="$gnuArch" \ 126 | # "/usr/src/postgresql/src/backend/access/common/tupconvert.c:105: undefined reference to `libintl_gettext'" 127 | # --enable-nls \ 128 | --enable-integer-datetimes \ 129 | --enable-thread-safety \ 130 | --enable-tap-tests \ 131 | # skip debugging info -- we want tiny size instead 132 | # --enable-debug \ 133 | --disable-rpath \ 134 | --with-uuid=e2fs \ 135 | --with-gnu-ld \ 136 | --with-pgport=5432 \ 137 | --with-system-tzdata=/usr/share/zoneinfo \ 138 | --prefix=/usr/local \ 139 | --with-includes=/usr/local/include \ 140 | --with-libraries=/usr/local/lib \ 141 | --with-gssapi \ 142 | --with-ldap \ 143 | --with-tcl \ 144 | --with-perl \ 145 | --with-python \ 146 | # --with-pam \ 147 | --with-openssl \ 148 | --with-libxml \ 149 | --with-libxslt \ 150 | --with-icu \ 151 | --with-llvm \ 152 | --with-lz4 \ 153 | --with-zstd \ 154 | ; \ 155 | make -j "$(nproc)" world-bin; \ 156 | make install-world-bin; \ 157 | make -C contrib install; \ 158 | \ 159 | runDeps="$( \ 160 | scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \ 161 | | tr ',' '\n' \ 162 | | sort -u \ 163 | | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ 164 | # Remove plperl, plpython and pltcl dependencies by default to save image size 165 | # To use the pl extensions, those have to be installed in a derived image 166 | | grep -v -e perl -e python -e tcl \ 167 | )"; \ 168 | apk add --no-cache --virtual .postgresql-rundeps \ 169 | $runDeps \ 170 | bash \ 171 | tzdata \ 172 | zstd \ 173 | # https://wiki.alpinelinux.org/wiki/Release_Notes_for_Alpine_3.16.0#ICU_data_split 174 | icu-data-full \ 175 | # https://git.alpinelinux.org/aports/tree/community/nss_wrapper/APKBUILD?h=3.22-stable#n7 ("ppc64le: test case segfaults") 176 | $([ "$(apk --print-arch)" != 'ppc64le' ] && echo 'nss_wrapper') \ 177 | ; \ 178 | apk del --no-network .build-deps; \ 179 | cd /; \ 180 | rm -rf \ 181 | /usr/src/postgresql \ 182 | /usr/local/share/doc \ 183 | /usr/local/share/man \ 184 | ; \ 185 | \ 186 | postgres --version 187 | 188 | # make the sample config easier to munge (and "correct by default") 189 | RUN set -eux; \ 190 | cp -v /usr/local/share/postgresql/postgresql.conf.sample /usr/local/share/postgresql/postgresql.conf.sample.orig; \ 191 | sed -ri "s!^#?(listen_addresses)\s*=\s*\S+.*!\1 = '*'!" /usr/local/share/postgresql/postgresql.conf.sample; \ 192 | grep -F "listen_addresses = '*'" /usr/local/share/postgresql/postgresql.conf.sample 193 | 194 | RUN install --verbose --directory --owner postgres --group postgres --mode 3777 /var/run/postgresql 195 | 196 | ENV PGDATA /var/lib/postgresql/data 197 | # this 1777 will be replaced by 0700 at runtime (allows semi-arbitrary "--user" values) 198 | RUN install --verbose --directory --owner postgres --group postgres --mode 1777 "$PGDATA" 199 | VOLUME /var/lib/postgresql/data 200 | 201 | COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ 202 | RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh 203 | ENTRYPOINT ["docker-entrypoint.sh"] 204 | 205 | # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL 206 | # calls "Fast Shutdown mode" wherein new connections are disallowed and any 207 | # in-progress transactions are aborted, allowing PostgreSQL to stop cleanly and 208 | # flush tables to disk. 209 | # 210 | # See https://www.postgresql.org/docs/current/server-shutdown.html for more details 211 | # about available PostgreSQL server shutdown signals. 212 | # 213 | # See also https://www.postgresql.org/docs/current/server-start.html for further 214 | # justification of this as the default value, namely that the example (and 215 | # shipped) systemd service files use the "Fast Shutdown mode" for service 216 | # termination. 217 | # 218 | STOPSIGNAL SIGINT 219 | # 220 | # An additional setting that is recommended for all users regardless of this 221 | # value is the runtime "--stop-timeout" (or your orchestrator/runtime's 222 | # equivalent) for controlling how long to wait between sending the defined 223 | # STOPSIGNAL and sending SIGKILL. 224 | # 225 | # The default in most runtimes (such as Docker) is 10 seconds, and the 226 | # documentation at https://www.postgresql.org/docs/current/server-start.html notes 227 | # that even 90 seconds may not be long enough in many instances. 228 | 229 | EXPOSE 5432 230 | CMD ["postgres"] 231 | -------------------------------------------------------------------------------- /15/alpine3.22/docker-ensure-initdb.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | # 5 | # This script is intended for three main use cases: 6 | # 7 | # 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior 8 | # 9 | # 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution 10 | # (no-op if database is already initialized) 11 | # 12 | # 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use 13 | # (error if database is already initialized) 14 | # 15 | 16 | source /usr/local/bin/docker-entrypoint.sh 17 | 18 | # arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) 19 | if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then 20 | set -- postgres "$@" 21 | fi 22 | 23 | # see also "_main" in "docker-entrypoint.sh" 24 | 25 | docker_setup_env 26 | # setup data directories and permissions (when run as root) 27 | docker_create_db_directories 28 | if [ "$(id -u)" = '0' ]; then 29 | # then restart script as postgres user 30 | exec gosu postgres "$BASH_SOURCE" "$@" 31 | fi 32 | 33 | # only run initialization on an empty data directory 34 | if [ -z "$DATABASE_ALREADY_EXISTS" ]; then 35 | docker_verify_minimum_env 36 | 37 | # check dir permissions to reduce likelihood of half-initialized database 38 | ls /docker-entrypoint-initdb.d/ > /dev/null 39 | 40 | docker_init_database_dir 41 | pg_setup_hba_conf "$@" 42 | 43 | # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless 44 | # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS 45 | export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" 46 | docker_temp_server_start "$@" 47 | 48 | docker_setup_db 49 | docker_process_init_files /docker-entrypoint-initdb.d/* 50 | 51 | docker_temp_server_stop 52 | unset PGPASSWORD 53 | else 54 | self="$(basename "$0")" 55 | case "$self" in 56 | docker-ensure-initdb.sh) 57 | echo >&2 "$self: note: database already initialized in '$PGDATA'!" 58 | exit 0 59 | ;; 60 | 61 | docker-enforce-initdb.sh) 62 | echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" 63 | exit 1 64 | ;; 65 | 66 | *) 67 | echo >&2 "$self: error: unknown file name: $self" 68 | exit 99 69 | ;; 70 | esac 71 | fi 72 | -------------------------------------------------------------------------------- /15/bookworm/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" 3 | # 4 | # PLEASE DO NOT EDIT IT DIRECTLY. 5 | # 6 | 7 | FROM debian:bookworm-slim 8 | 9 | # explicitly set user/group IDs 10 | RUN set -eux; \ 11 | groupadd -r postgres --gid=999; \ 12 | # https://salsa.debian.org/postgresql/postgresql-common/blob/997d842ee744687d99a2b2d95c1083a2615c79e8/debian/postgresql-common.postinst#L32-35 13 | useradd -r -g postgres --uid=999 --home-dir=/var/lib/postgresql --shell=/bin/bash postgres; \ 14 | # also create the postgres user's home directory with appropriate permissions 15 | # see https://github.com/docker-library/postgres/issues/274 16 | install --verbose --directory --owner postgres --group postgres --mode 1777 /var/lib/postgresql 17 | 18 | RUN set -ex; \ 19 | apt-get update; \ 20 | apt-get install -y --no-install-recommends \ 21 | gnupg \ 22 | # https://www.postgresql.org/docs/16/app-psql.html#APP-PSQL-META-COMMAND-PSET-PAGER 23 | # https://github.com/postgres/postgres/blob/REL_16_1/src/include/fe_utils/print.h#L25 24 | # (if "less" is available, it gets used as the default pager for psql, and it only adds ~1.5MiB to our image size) 25 | less \ 26 | ; \ 27 | rm -rf /var/lib/apt/lists/* 28 | 29 | # grab gosu for easy step-down from root 30 | # https://github.com/tianon/gosu/releases 31 | ENV GOSU_VERSION 1.17 32 | RUN set -eux; \ 33 | savedAptMark="$(apt-mark showmanual)"; \ 34 | apt-get update; \ 35 | apt-get install -y --no-install-recommends ca-certificates wget; \ 36 | rm -rf /var/lib/apt/lists/*; \ 37 | dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \ 38 | wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \ 39 | wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \ 40 | export GNUPGHOME="$(mktemp -d)"; \ 41 | gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ 42 | gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \ 43 | gpgconf --kill all; \ 44 | rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \ 45 | apt-mark auto '.*' > /dev/null; \ 46 | [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; \ 47 | apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ 48 | chmod +x /usr/local/bin/gosu; \ 49 | gosu --version; \ 50 | gosu nobody true 51 | 52 | # make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default 53 | RUN set -eux; \ 54 | if [ -f /etc/dpkg/dpkg.cfg.d/docker ]; then \ 55 | # if this file exists, we're likely in "debian:xxx-slim", and locales are thus being excluded so we need to remove that exclusion (since we need locales) 56 | grep -q '/usr/share/locale' /etc/dpkg/dpkg.cfg.d/docker; \ 57 | sed -ri '/\/usr\/share\/locale/d' /etc/dpkg/dpkg.cfg.d/docker; \ 58 | ! grep -q '/usr/share/locale' /etc/dpkg/dpkg.cfg.d/docker; \ 59 | fi; \ 60 | apt-get update; apt-get install -y --no-install-recommends locales; rm -rf /var/lib/apt/lists/*; \ 61 | echo 'en_US.UTF-8 UTF-8' >> /etc/locale.gen; \ 62 | locale-gen; \ 63 | locale -a | grep 'en_US.utf8' 64 | ENV LANG en_US.utf8 65 | 66 | RUN set -eux; \ 67 | apt-get update; \ 68 | apt-get install -y --no-install-recommends \ 69 | libnss-wrapper \ 70 | xz-utils \ 71 | zstd \ 72 | ; \ 73 | rm -rf /var/lib/apt/lists/* 74 | 75 | RUN mkdir /docker-entrypoint-initdb.d 76 | 77 | RUN set -ex; \ 78 | # pub 4096R/ACCC4CF8 2011-10-13 [expires: 2019-07-02] 79 | # Key fingerprint = B97B 0AFC AA1A 47F0 44F2 44A0 7FCC 7D46 ACCC 4CF8 80 | # uid PostgreSQL Debian Repository 81 | key='B97B0AFCAA1A47F044F244A07FCC7D46ACCC4CF8'; \ 82 | export GNUPGHOME="$(mktemp -d)"; \ 83 | mkdir -p /usr/local/share/keyrings/; \ 84 | gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \ 85 | gpg --batch --export --armor "$key" > /usr/local/share/keyrings/postgres.gpg.asc; \ 86 | gpgconf --kill all; \ 87 | rm -rf "$GNUPGHOME" 88 | 89 | ENV PG_MAJOR 15 90 | ENV PATH $PATH:/usr/lib/postgresql/$PG_MAJOR/bin 91 | 92 | ENV PG_VERSION 15.13-1.pgdg120+1 93 | 94 | RUN set -ex; \ 95 | \ 96 | # see note below about "*.pyc" files 97 | export PYTHONDONTWRITEBYTECODE=1; \ 98 | \ 99 | dpkgArch="$(dpkg --print-architecture)"; \ 100 | aptRepo="[ signed-by=/usr/local/share/keyrings/postgres.gpg.asc ] http://apt.postgresql.org/pub/repos/apt/ bookworm-pgdg main $PG_MAJOR"; \ 101 | case "$dpkgArch" in \ 102 | amd64 | arm64 | ppc64el) \ 103 | # arches officialy built by upstream 104 | echo "deb $aptRepo" > /etc/apt/sources.list.d/pgdg.list; \ 105 | apt-get update; \ 106 | ;; \ 107 | *) \ 108 | # we're on an architecture upstream doesn't officially build for 109 | # let's build binaries from their published source packages 110 | echo "deb-src $aptRepo" > /etc/apt/sources.list.d/pgdg.list; \ 111 | \ 112 | savedAptMark="$(apt-mark showmanual)"; \ 113 | \ 114 | tempDir="$(mktemp -d)"; \ 115 | cd "$tempDir"; \ 116 | \ 117 | # create a temporary local APT repo to install from (so that dependency resolution can be handled by APT, as it should be) 118 | apt-get update; \ 119 | apt-get install -y --no-install-recommends dpkg-dev; \ 120 | echo "deb [ trusted=yes ] file://$tempDir ./" > /etc/apt/sources.list.d/temp.list; \ 121 | _update_repo() { \ 122 | dpkg-scanpackages . > Packages; \ 123 | # work around the following APT issue by using "Acquire::GzipIndexes=false" (overriding "/etc/apt/apt.conf.d/docker-gzip-indexes") 124 | # Could not open file /var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages - open (13: Permission denied) 125 | # ... 126 | # E: Failed to fetch store:/var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages Could not open file /var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages - open (13: Permission denied) 127 | apt-get -o Acquire::GzipIndexes=false update; \ 128 | }; \ 129 | _update_repo; \ 130 | \ 131 | # build .deb files from upstream's source packages (which are verified by apt-get) 132 | nproc="$(nproc)"; \ 133 | export DEB_BUILD_OPTIONS="nocheck parallel=$nproc"; \ 134 | # we have to build postgresql-common-dev first because postgresql-$PG_MAJOR shares "debian/rules" logic with it: https://salsa.debian.org/postgresql/postgresql/-/commit/f4338a0d28cf4541956bddb0f4e444ba9dba81b9 135 | apt-get build-dep -y postgresql-common-dev; \ 136 | apt-get source --compile postgresql-common-dev; \ 137 | _update_repo; \ 138 | apt-get build-dep -y "postgresql-$PG_MAJOR=$PG_VERSION"; \ 139 | apt-get source --compile "postgresql-$PG_MAJOR=$PG_VERSION"; \ 140 | \ 141 | # we don't remove APT lists here because they get re-downloaded and removed later 142 | \ 143 | # reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies 144 | # (which is done after we install the built packages so we don't have to redownload any overlapping dependencies) 145 | apt-mark showmanual | xargs apt-mark auto > /dev/null; \ 146 | apt-mark manual $savedAptMark; \ 147 | \ 148 | ls -lAFh; \ 149 | _update_repo; \ 150 | grep '^Package: ' Packages; \ 151 | cd /; \ 152 | ;; \ 153 | esac; \ 154 | \ 155 | apt-get install -y --no-install-recommends postgresql-common; \ 156 | sed -ri 's/#(create_main_cluster) .*$/\1 = false/' /etc/postgresql-common/createcluster.conf; \ 157 | apt-get install -y --no-install-recommends \ 158 | "postgresql-$PG_MAJOR=$PG_VERSION" \ 159 | ; \ 160 | \ 161 | rm -rf /var/lib/apt/lists/*; \ 162 | \ 163 | if [ -n "$tempDir" ]; then \ 164 | # if we have leftovers from building, let's purge them (including extra, unnecessary build deps) 165 | apt-get purge -y --auto-remove; \ 166 | rm -rf "$tempDir" /etc/apt/sources.list.d/temp.list; \ 167 | fi; \ 168 | \ 169 | # some of the steps above generate a lot of "*.pyc" files (and setting "PYTHONDONTWRITEBYTECODE" beforehand doesn't propagate properly for some reason), so we clean them up manually (as long as they aren't owned by a package) 170 | find /usr -name '*.pyc' -type f -exec bash -c 'for pyc; do dpkg -S "$pyc" &> /dev/null || rm -vf "$pyc"; done' -- '{}' +; \ 171 | \ 172 | postgres --version 173 | 174 | # make the sample config easier to munge (and "correct by default") 175 | RUN set -eux; \ 176 | dpkg-divert --add --rename --divert "/usr/share/postgresql/postgresql.conf.sample.dpkg" "/usr/share/postgresql/$PG_MAJOR/postgresql.conf.sample"; \ 177 | cp -v /usr/share/postgresql/postgresql.conf.sample.dpkg /usr/share/postgresql/postgresql.conf.sample; \ 178 | ln -sv ../postgresql.conf.sample "/usr/share/postgresql/$PG_MAJOR/"; \ 179 | sed -ri "s!^#?(listen_addresses)\s*=\s*\S+.*!\1 = '*'!" /usr/share/postgresql/postgresql.conf.sample; \ 180 | grep -F "listen_addresses = '*'" /usr/share/postgresql/postgresql.conf.sample 181 | 182 | RUN install --verbose --directory --owner postgres --group postgres --mode 3777 /var/run/postgresql 183 | 184 | ENV PGDATA /var/lib/postgresql/data 185 | # this 1777 will be replaced by 0700 at runtime (allows semi-arbitrary "--user" values) 186 | RUN install --verbose --directory --owner postgres --group postgres --mode 1777 "$PGDATA" 187 | VOLUME /var/lib/postgresql/data 188 | 189 | COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ 190 | RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh 191 | ENTRYPOINT ["docker-entrypoint.sh"] 192 | 193 | # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL 194 | # calls "Fast Shutdown mode" wherein new connections are disallowed and any 195 | # in-progress transactions are aborted, allowing PostgreSQL to stop cleanly and 196 | # flush tables to disk. 197 | # 198 | # See https://www.postgresql.org/docs/current/server-shutdown.html for more details 199 | # about available PostgreSQL server shutdown signals. 200 | # 201 | # See also https://www.postgresql.org/docs/current/server-start.html for further 202 | # justification of this as the default value, namely that the example (and 203 | # shipped) systemd service files use the "Fast Shutdown mode" for service 204 | # termination. 205 | # 206 | STOPSIGNAL SIGINT 207 | # 208 | # An additional setting that is recommended for all users regardless of this 209 | # value is the runtime "--stop-timeout" (or your orchestrator/runtime's 210 | # equivalent) for controlling how long to wait between sending the defined 211 | # STOPSIGNAL and sending SIGKILL. 212 | # 213 | # The default in most runtimes (such as Docker) is 10 seconds, and the 214 | # documentation at https://www.postgresql.org/docs/current/server-start.html notes 215 | # that even 90 seconds may not be long enough in many instances. 216 | 217 | EXPOSE 5432 218 | CMD ["postgres"] 219 | -------------------------------------------------------------------------------- /15/bookworm/docker-ensure-initdb.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | # 5 | # This script is intended for three main use cases: 6 | # 7 | # 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior 8 | # 9 | # 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution 10 | # (no-op if database is already initialized) 11 | # 12 | # 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use 13 | # (error if database is already initialized) 14 | # 15 | 16 | source /usr/local/bin/docker-entrypoint.sh 17 | 18 | # arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) 19 | if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then 20 | set -- postgres "$@" 21 | fi 22 | 23 | # see also "_main" in "docker-entrypoint.sh" 24 | 25 | docker_setup_env 26 | # setup data directories and permissions (when run as root) 27 | docker_create_db_directories 28 | if [ "$(id -u)" = '0' ]; then 29 | # then restart script as postgres user 30 | exec gosu postgres "$BASH_SOURCE" "$@" 31 | fi 32 | 33 | # only run initialization on an empty data directory 34 | if [ -z "$DATABASE_ALREADY_EXISTS" ]; then 35 | docker_verify_minimum_env 36 | 37 | # check dir permissions to reduce likelihood of half-initialized database 38 | ls /docker-entrypoint-initdb.d/ > /dev/null 39 | 40 | docker_init_database_dir 41 | pg_setup_hba_conf "$@" 42 | 43 | # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless 44 | # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS 45 | export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" 46 | docker_temp_server_start "$@" 47 | 48 | docker_setup_db 49 | docker_process_init_files /docker-entrypoint-initdb.d/* 50 | 51 | docker_temp_server_stop 52 | unset PGPASSWORD 53 | else 54 | self="$(basename "$0")" 55 | case "$self" in 56 | docker-ensure-initdb.sh) 57 | echo >&2 "$self: note: database already initialized in '$PGDATA'!" 58 | exit 0 59 | ;; 60 | 61 | docker-enforce-initdb.sh) 62 | echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" 63 | exit 1 64 | ;; 65 | 66 | *) 67 | echo >&2 "$self: error: unknown file name: $self" 68 | exit 99 69 | ;; 70 | esac 71 | fi 72 | -------------------------------------------------------------------------------- /15/bullseye/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" 3 | # 4 | # PLEASE DO NOT EDIT IT DIRECTLY. 5 | # 6 | 7 | FROM debian:bullseye-slim 8 | 9 | # explicitly set user/group IDs 10 | RUN set -eux; \ 11 | groupadd -r postgres --gid=999; \ 12 | # https://salsa.debian.org/postgresql/postgresql-common/blob/997d842ee744687d99a2b2d95c1083a2615c79e8/debian/postgresql-common.postinst#L32-35 13 | useradd -r -g postgres --uid=999 --home-dir=/var/lib/postgresql --shell=/bin/bash postgres; \ 14 | # also create the postgres user's home directory with appropriate permissions 15 | # see https://github.com/docker-library/postgres/issues/274 16 | install --verbose --directory --owner postgres --group postgres --mode 1777 /var/lib/postgresql 17 | 18 | RUN set -ex; \ 19 | apt-get update; \ 20 | apt-get install -y --no-install-recommends \ 21 | gnupg \ 22 | # https://www.postgresql.org/docs/16/app-psql.html#APP-PSQL-META-COMMAND-PSET-PAGER 23 | # https://github.com/postgres/postgres/blob/REL_16_1/src/include/fe_utils/print.h#L25 24 | # (if "less" is available, it gets used as the default pager for psql, and it only adds ~1.5MiB to our image size) 25 | less \ 26 | ; \ 27 | rm -rf /var/lib/apt/lists/* 28 | 29 | # grab gosu for easy step-down from root 30 | # https://github.com/tianon/gosu/releases 31 | ENV GOSU_VERSION 1.17 32 | RUN set -eux; \ 33 | savedAptMark="$(apt-mark showmanual)"; \ 34 | apt-get update; \ 35 | apt-get install -y --no-install-recommends ca-certificates wget; \ 36 | rm -rf /var/lib/apt/lists/*; \ 37 | dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \ 38 | wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \ 39 | wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \ 40 | export GNUPGHOME="$(mktemp -d)"; \ 41 | gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ 42 | gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \ 43 | gpgconf --kill all; \ 44 | rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \ 45 | apt-mark auto '.*' > /dev/null; \ 46 | [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; \ 47 | apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ 48 | chmod +x /usr/local/bin/gosu; \ 49 | gosu --version; \ 50 | gosu nobody true 51 | 52 | # make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default 53 | RUN set -eux; \ 54 | if [ -f /etc/dpkg/dpkg.cfg.d/docker ]; then \ 55 | # if this file exists, we're likely in "debian:xxx-slim", and locales are thus being excluded so we need to remove that exclusion (since we need locales) 56 | grep -q '/usr/share/locale' /etc/dpkg/dpkg.cfg.d/docker; \ 57 | sed -ri '/\/usr\/share\/locale/d' /etc/dpkg/dpkg.cfg.d/docker; \ 58 | ! grep -q '/usr/share/locale' /etc/dpkg/dpkg.cfg.d/docker; \ 59 | fi; \ 60 | apt-get update; apt-get install -y --no-install-recommends locales; rm -rf /var/lib/apt/lists/*; \ 61 | echo 'en_US.UTF-8 UTF-8' >> /etc/locale.gen; \ 62 | locale-gen; \ 63 | locale -a | grep 'en_US.utf8' 64 | ENV LANG en_US.utf8 65 | 66 | RUN set -eux; \ 67 | apt-get update; \ 68 | apt-get install -y --no-install-recommends \ 69 | libnss-wrapper \ 70 | xz-utils \ 71 | zstd \ 72 | ; \ 73 | rm -rf /var/lib/apt/lists/* 74 | 75 | RUN mkdir /docker-entrypoint-initdb.d 76 | 77 | RUN set -ex; \ 78 | # pub 4096R/ACCC4CF8 2011-10-13 [expires: 2019-07-02] 79 | # Key fingerprint = B97B 0AFC AA1A 47F0 44F2 44A0 7FCC 7D46 ACCC 4CF8 80 | # uid PostgreSQL Debian Repository 81 | key='B97B0AFCAA1A47F044F244A07FCC7D46ACCC4CF8'; \ 82 | export GNUPGHOME="$(mktemp -d)"; \ 83 | mkdir -p /usr/local/share/keyrings/; \ 84 | gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \ 85 | gpg --batch --export --armor "$key" > /usr/local/share/keyrings/postgres.gpg.asc; \ 86 | gpgconf --kill all; \ 87 | rm -rf "$GNUPGHOME" 88 | 89 | ENV PG_MAJOR 15 90 | ENV PATH $PATH:/usr/lib/postgresql/$PG_MAJOR/bin 91 | 92 | ENV PG_VERSION 15.13-1.pgdg110+1 93 | 94 | RUN set -ex; \ 95 | \ 96 | # see note below about "*.pyc" files 97 | export PYTHONDONTWRITEBYTECODE=1; \ 98 | \ 99 | dpkgArch="$(dpkg --print-architecture)"; \ 100 | aptRepo="[ signed-by=/usr/local/share/keyrings/postgres.gpg.asc ] http://apt.postgresql.org/pub/repos/apt/ bullseye-pgdg main $PG_MAJOR"; \ 101 | case "$dpkgArch" in \ 102 | amd64 | arm64 | ppc64el) \ 103 | # arches officialy built by upstream 104 | echo "deb $aptRepo" > /etc/apt/sources.list.d/pgdg.list; \ 105 | apt-get update; \ 106 | ;; \ 107 | *) \ 108 | # we're on an architecture upstream doesn't officially build for 109 | # let's build binaries from their published source packages 110 | echo "deb-src $aptRepo" > /etc/apt/sources.list.d/pgdg.list; \ 111 | \ 112 | savedAptMark="$(apt-mark showmanual)"; \ 113 | \ 114 | tempDir="$(mktemp -d)"; \ 115 | cd "$tempDir"; \ 116 | \ 117 | # create a temporary local APT repo to install from (so that dependency resolution can be handled by APT, as it should be) 118 | apt-get update; \ 119 | apt-get install -y --no-install-recommends dpkg-dev; \ 120 | echo "deb [ trusted=yes ] file://$tempDir ./" > /etc/apt/sources.list.d/temp.list; \ 121 | _update_repo() { \ 122 | dpkg-scanpackages . > Packages; \ 123 | # work around the following APT issue by using "Acquire::GzipIndexes=false" (overriding "/etc/apt/apt.conf.d/docker-gzip-indexes") 124 | # Could not open file /var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages - open (13: Permission denied) 125 | # ... 126 | # E: Failed to fetch store:/var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages Could not open file /var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages - open (13: Permission denied) 127 | apt-get -o Acquire::GzipIndexes=false update; \ 128 | }; \ 129 | _update_repo; \ 130 | \ 131 | # build .deb files from upstream's source packages (which are verified by apt-get) 132 | nproc="$(nproc)"; \ 133 | export DEB_BUILD_OPTIONS="nocheck parallel=$nproc"; \ 134 | # we have to build postgresql-common-dev first because postgresql-$PG_MAJOR shares "debian/rules" logic with it: https://salsa.debian.org/postgresql/postgresql/-/commit/f4338a0d28cf4541956bddb0f4e444ba9dba81b9 135 | apt-get build-dep -y postgresql-common-dev; \ 136 | apt-get source --compile postgresql-common-dev; \ 137 | _update_repo; \ 138 | apt-get build-dep -y "postgresql-$PG_MAJOR=$PG_VERSION"; \ 139 | apt-get source --compile "postgresql-$PG_MAJOR=$PG_VERSION"; \ 140 | \ 141 | # we don't remove APT lists here because they get re-downloaded and removed later 142 | \ 143 | # reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies 144 | # (which is done after we install the built packages so we don't have to redownload any overlapping dependencies) 145 | apt-mark showmanual | xargs apt-mark auto > /dev/null; \ 146 | apt-mark manual $savedAptMark; \ 147 | \ 148 | ls -lAFh; \ 149 | _update_repo; \ 150 | grep '^Package: ' Packages; \ 151 | cd /; \ 152 | ;; \ 153 | esac; \ 154 | \ 155 | apt-get install -y --no-install-recommends postgresql-common; \ 156 | sed -ri 's/#(create_main_cluster) .*$/\1 = false/' /etc/postgresql-common/createcluster.conf; \ 157 | apt-get install -y --no-install-recommends \ 158 | "postgresql-$PG_MAJOR=$PG_VERSION" \ 159 | ; \ 160 | \ 161 | rm -rf /var/lib/apt/lists/*; \ 162 | \ 163 | if [ -n "$tempDir" ]; then \ 164 | # if we have leftovers from building, let's purge them (including extra, unnecessary build deps) 165 | apt-get purge -y --auto-remove; \ 166 | rm -rf "$tempDir" /etc/apt/sources.list.d/temp.list; \ 167 | fi; \ 168 | \ 169 | # some of the steps above generate a lot of "*.pyc" files (and setting "PYTHONDONTWRITEBYTECODE" beforehand doesn't propagate properly for some reason), so we clean them up manually (as long as they aren't owned by a package) 170 | find /usr -name '*.pyc' -type f -exec bash -c 'for pyc; do dpkg -S "$pyc" &> /dev/null || rm -vf "$pyc"; done' -- '{}' +; \ 171 | \ 172 | postgres --version 173 | 174 | # make the sample config easier to munge (and "correct by default") 175 | RUN set -eux; \ 176 | dpkg-divert --add --rename --divert "/usr/share/postgresql/postgresql.conf.sample.dpkg" "/usr/share/postgresql/$PG_MAJOR/postgresql.conf.sample"; \ 177 | cp -v /usr/share/postgresql/postgresql.conf.sample.dpkg /usr/share/postgresql/postgresql.conf.sample; \ 178 | ln -sv ../postgresql.conf.sample "/usr/share/postgresql/$PG_MAJOR/"; \ 179 | sed -ri "s!^#?(listen_addresses)\s*=\s*\S+.*!\1 = '*'!" /usr/share/postgresql/postgresql.conf.sample; \ 180 | grep -F "listen_addresses = '*'" /usr/share/postgresql/postgresql.conf.sample 181 | 182 | RUN install --verbose --directory --owner postgres --group postgres --mode 3777 /var/run/postgresql 183 | 184 | ENV PGDATA /var/lib/postgresql/data 185 | # this 1777 will be replaced by 0700 at runtime (allows semi-arbitrary "--user" values) 186 | RUN install --verbose --directory --owner postgres --group postgres --mode 1777 "$PGDATA" 187 | VOLUME /var/lib/postgresql/data 188 | 189 | COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ 190 | RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh 191 | ENTRYPOINT ["docker-entrypoint.sh"] 192 | 193 | # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL 194 | # calls "Fast Shutdown mode" wherein new connections are disallowed and any 195 | # in-progress transactions are aborted, allowing PostgreSQL to stop cleanly and 196 | # flush tables to disk. 197 | # 198 | # See https://www.postgresql.org/docs/current/server-shutdown.html for more details 199 | # about available PostgreSQL server shutdown signals. 200 | # 201 | # See also https://www.postgresql.org/docs/current/server-start.html for further 202 | # justification of this as the default value, namely that the example (and 203 | # shipped) systemd service files use the "Fast Shutdown mode" for service 204 | # termination. 205 | # 206 | STOPSIGNAL SIGINT 207 | # 208 | # An additional setting that is recommended for all users regardless of this 209 | # value is the runtime "--stop-timeout" (or your orchestrator/runtime's 210 | # equivalent) for controlling how long to wait between sending the defined 211 | # STOPSIGNAL and sending SIGKILL. 212 | # 213 | # The default in most runtimes (such as Docker) is 10 seconds, and the 214 | # documentation at https://www.postgresql.org/docs/current/server-start.html notes 215 | # that even 90 seconds may not be long enough in many instances. 216 | 217 | EXPOSE 5432 218 | CMD ["postgres"] 219 | -------------------------------------------------------------------------------- /15/bullseye/docker-ensure-initdb.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | # 5 | # This script is intended for three main use cases: 6 | # 7 | # 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior 8 | # 9 | # 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution 10 | # (no-op if database is already initialized) 11 | # 12 | # 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use 13 | # (error if database is already initialized) 14 | # 15 | 16 | source /usr/local/bin/docker-entrypoint.sh 17 | 18 | # arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) 19 | if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then 20 | set -- postgres "$@" 21 | fi 22 | 23 | # see also "_main" in "docker-entrypoint.sh" 24 | 25 | docker_setup_env 26 | # setup data directories and permissions (when run as root) 27 | docker_create_db_directories 28 | if [ "$(id -u)" = '0' ]; then 29 | # then restart script as postgres user 30 | exec gosu postgres "$BASH_SOURCE" "$@" 31 | fi 32 | 33 | # only run initialization on an empty data directory 34 | if [ -z "$DATABASE_ALREADY_EXISTS" ]; then 35 | docker_verify_minimum_env 36 | 37 | # check dir permissions to reduce likelihood of half-initialized database 38 | ls /docker-entrypoint-initdb.d/ > /dev/null 39 | 40 | docker_init_database_dir 41 | pg_setup_hba_conf "$@" 42 | 43 | # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless 44 | # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS 45 | export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" 46 | docker_temp_server_start "$@" 47 | 48 | docker_setup_db 49 | docker_process_init_files /docker-entrypoint-initdb.d/* 50 | 51 | docker_temp_server_stop 52 | unset PGPASSWORD 53 | else 54 | self="$(basename "$0")" 55 | case "$self" in 56 | docker-ensure-initdb.sh) 57 | echo >&2 "$self: note: database already initialized in '$PGDATA'!" 58 | exit 0 59 | ;; 60 | 61 | docker-enforce-initdb.sh) 62 | echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" 63 | exit 1 64 | ;; 65 | 66 | *) 67 | echo >&2 "$self: error: unknown file name: $self" 68 | exit 99 69 | ;; 70 | esac 71 | fi 72 | -------------------------------------------------------------------------------- /16/alpine3.21/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" 3 | # 4 | # PLEASE DO NOT EDIT IT DIRECTLY. 5 | # 6 | 7 | FROM alpine:3.21 8 | 9 | # 70 is the standard uid/gid for "postgres" in Alpine 10 | # https://git.alpinelinux.org/aports/tree/main/postgresql-common/postgresql-common.pre-install?h=3.22-stable 11 | RUN set -eux; \ 12 | addgroup -g 70 -S postgres; \ 13 | adduser -u 70 -S -D -G postgres -H -h /var/lib/postgresql -s /bin/sh postgres; \ 14 | # also create the postgres user's home directory with appropriate permissions 15 | # see https://github.com/docker-library/postgres/issues/274 16 | install --verbose --directory --owner postgres --group postgres --mode 1777 /var/lib/postgresql 17 | 18 | # grab gosu for easy step-down from root 19 | # https://github.com/tianon/gosu/releases 20 | ENV GOSU_VERSION 1.17 21 | RUN set -eux; \ 22 | \ 23 | apk add --no-cache --virtual .gosu-deps \ 24 | ca-certificates \ 25 | dpkg \ 26 | gnupg \ 27 | ; \ 28 | \ 29 | dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \ 30 | wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \ 31 | wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \ 32 | \ 33 | # verify the signature 34 | export GNUPGHOME="$(mktemp -d)"; \ 35 | gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ 36 | gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \ 37 | gpgconf --kill all; \ 38 | rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \ 39 | \ 40 | # clean up fetch dependencies 41 | apk del --no-network .gosu-deps; \ 42 | \ 43 | chmod +x /usr/local/bin/gosu; \ 44 | # verify that the binary works 45 | gosu --version; \ 46 | gosu nobody true 47 | RUN set -eux; ln -svf gosu /usr/local/bin/su-exec; su-exec nobody true # backwards compatibility (removed in PostgreSQL 17+) 48 | 49 | # make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default 50 | # alpine doesn't require explicit locale-file generation 51 | ENV LANG en_US.utf8 52 | 53 | RUN mkdir /docker-entrypoint-initdb.d 54 | 55 | ENV PG_MAJOR 16 56 | ENV PG_VERSION 16.9 57 | ENV PG_SHA256 07c00fb824df0a0c295f249f44691b86e3266753b380c96f633c3311e10bd005 58 | 59 | ENV DOCKER_PG_LLVM_DEPS \ 60 | llvm19-dev \ 61 | clang19 62 | 63 | RUN set -eux; \ 64 | \ 65 | wget -O postgresql.tar.bz2 "https://ftp.postgresql.org/pub/source/v$PG_VERSION/postgresql-$PG_VERSION.tar.bz2"; \ 66 | echo "$PG_SHA256 *postgresql.tar.bz2" | sha256sum -c -; \ 67 | mkdir -p /usr/src/postgresql; \ 68 | tar \ 69 | --extract \ 70 | --file postgresql.tar.bz2 \ 71 | --directory /usr/src/postgresql \ 72 | --strip-components 1 \ 73 | ; \ 74 | rm postgresql.tar.bz2; \ 75 | \ 76 | apk add --no-cache --virtual .build-deps \ 77 | $DOCKER_PG_LLVM_DEPS \ 78 | bison \ 79 | coreutils \ 80 | dpkg-dev dpkg \ 81 | flex \ 82 | g++ \ 83 | gcc \ 84 | krb5-dev \ 85 | libc-dev \ 86 | libedit-dev \ 87 | libxml2-dev \ 88 | libxslt-dev \ 89 | linux-headers \ 90 | make \ 91 | openldap-dev \ 92 | openssl-dev \ 93 | perl-dev \ 94 | perl-ipc-run \ 95 | perl-utils \ 96 | python3-dev \ 97 | tcl-dev \ 98 | util-linux-dev \ 99 | zlib-dev \ 100 | # https://www.postgresql.org/docs/10/static/release-10.html#id-1.11.6.9.5.13 101 | icu-dev \ 102 | # https://www.postgresql.org/docs/14/release-14.html#id-1.11.6.5.5.3.7 103 | lz4-dev \ 104 | # https://www.postgresql.org/docs/15/release-15.html "--with-zstd to enable Zstandard builds" 105 | zstd-dev \ 106 | ; \ 107 | \ 108 | cd /usr/src/postgresql; \ 109 | # update "DEFAULT_PGSOCKET_DIR" to "/var/run/postgresql" (matching Debian) 110 | # see https://anonscm.debian.org/git/pkg-postgresql/postgresql.git/tree/debian/patches/51-default-sockets-in-var.patch?id=8b539fcb3e093a521c095e70bdfa76887217b89f 111 | awk '$1 == "#define" && $2 == "DEFAULT_PGSOCKET_DIR" && $3 == "\"/tmp\"" { $3 = "\"/var/run/postgresql\""; print; next } { print }' src/include/pg_config_manual.h > src/include/pg_config_manual.h.new; \ 112 | grep '/var/run/postgresql' src/include/pg_config_manual.h.new; \ 113 | mv src/include/pg_config_manual.h.new src/include/pg_config_manual.h; \ 114 | gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \ 115 | \ 116 | # https://git.alpinelinux.org/aports/tree/community/postgresql15/APKBUILD?h=3.22-stable#n176 ("export LLVM_CONFIG") 117 | export LLVM_CONFIG="/usr/lib/llvm19/bin/llvm-config"; \ 118 | # https://git.alpinelinux.org/aports/tree/community/postgresql15/APKBUILD?h=3.22-stable#n180 ("older clang versions don't have a 'clang' exe anymore.") 119 | export CLANG=clang-19; \ 120 | \ 121 | # configure options taken from: 122 | # https://anonscm.debian.org/cgit/pkg-postgresql/postgresql.git/tree/debian/rules?h=9.5 123 | ./configure \ 124 | --enable-option-checking=fatal \ 125 | --build="$gnuArch" \ 126 | # "/usr/src/postgresql/src/backend/access/common/tupconvert.c:105: undefined reference to `libintl_gettext'" 127 | # --enable-nls \ 128 | --enable-integer-datetimes \ 129 | --enable-thread-safety \ 130 | --enable-tap-tests \ 131 | # skip debugging info -- we want tiny size instead 132 | # --enable-debug \ 133 | --disable-rpath \ 134 | --with-uuid=e2fs \ 135 | --with-pgport=5432 \ 136 | --with-system-tzdata=/usr/share/zoneinfo \ 137 | --prefix=/usr/local \ 138 | --with-includes=/usr/local/include \ 139 | --with-libraries=/usr/local/lib \ 140 | --with-gssapi \ 141 | --with-ldap \ 142 | --with-tcl \ 143 | --with-perl \ 144 | --with-python \ 145 | # --with-pam \ 146 | --with-openssl \ 147 | --with-libxml \ 148 | --with-libxslt \ 149 | --with-icu \ 150 | --with-llvm \ 151 | --with-lz4 \ 152 | --with-zstd \ 153 | ; \ 154 | make -j "$(nproc)" world-bin; \ 155 | make install-world-bin; \ 156 | make -C contrib install; \ 157 | \ 158 | runDeps="$( \ 159 | scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \ 160 | | tr ',' '\n' \ 161 | | sort -u \ 162 | | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ 163 | # Remove plperl, plpython and pltcl dependencies by default to save image size 164 | # To use the pl extensions, those have to be installed in a derived image 165 | | grep -v -e perl -e python -e tcl \ 166 | )"; \ 167 | apk add --no-cache --virtual .postgresql-rundeps \ 168 | $runDeps \ 169 | bash \ 170 | tzdata \ 171 | zstd \ 172 | # https://wiki.alpinelinux.org/wiki/Release_Notes_for_Alpine_3.16.0#ICU_data_split 173 | icu-data-full \ 174 | # https://git.alpinelinux.org/aports/tree/community/nss_wrapper/APKBUILD?h=3.22-stable#n7 ("ppc64le: test case segfaults") 175 | $([ "$(apk --print-arch)" != 'ppc64le' ] && echo 'nss_wrapper') \ 176 | ; \ 177 | apk del --no-network .build-deps; \ 178 | cd /; \ 179 | rm -rf \ 180 | /usr/src/postgresql \ 181 | /usr/local/share/doc \ 182 | /usr/local/share/man \ 183 | ; \ 184 | \ 185 | postgres --version 186 | 187 | # make the sample config easier to munge (and "correct by default") 188 | RUN set -eux; \ 189 | cp -v /usr/local/share/postgresql/postgresql.conf.sample /usr/local/share/postgresql/postgresql.conf.sample.orig; \ 190 | sed -ri "s!^#?(listen_addresses)\s*=\s*\S+.*!\1 = '*'!" /usr/local/share/postgresql/postgresql.conf.sample; \ 191 | grep -F "listen_addresses = '*'" /usr/local/share/postgresql/postgresql.conf.sample 192 | 193 | RUN install --verbose --directory --owner postgres --group postgres --mode 3777 /var/run/postgresql 194 | 195 | ENV PGDATA /var/lib/postgresql/data 196 | # this 1777 will be replaced by 0700 at runtime (allows semi-arbitrary "--user" values) 197 | RUN install --verbose --directory --owner postgres --group postgres --mode 1777 "$PGDATA" 198 | VOLUME /var/lib/postgresql/data 199 | 200 | COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ 201 | RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh 202 | ENTRYPOINT ["docker-entrypoint.sh"] 203 | 204 | # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL 205 | # calls "Fast Shutdown mode" wherein new connections are disallowed and any 206 | # in-progress transactions are aborted, allowing PostgreSQL to stop cleanly and 207 | # flush tables to disk. 208 | # 209 | # See https://www.postgresql.org/docs/current/server-shutdown.html for more details 210 | # about available PostgreSQL server shutdown signals. 211 | # 212 | # See also https://www.postgresql.org/docs/current/server-start.html for further 213 | # justification of this as the default value, namely that the example (and 214 | # shipped) systemd service files use the "Fast Shutdown mode" for service 215 | # termination. 216 | # 217 | STOPSIGNAL SIGINT 218 | # 219 | # An additional setting that is recommended for all users regardless of this 220 | # value is the runtime "--stop-timeout" (or your orchestrator/runtime's 221 | # equivalent) for controlling how long to wait between sending the defined 222 | # STOPSIGNAL and sending SIGKILL. 223 | # 224 | # The default in most runtimes (such as Docker) is 10 seconds, and the 225 | # documentation at https://www.postgresql.org/docs/current/server-start.html notes 226 | # that even 90 seconds may not be long enough in many instances. 227 | 228 | EXPOSE 5432 229 | CMD ["postgres"] 230 | -------------------------------------------------------------------------------- /16/alpine3.21/docker-ensure-initdb.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | # 5 | # This script is intended for three main use cases: 6 | # 7 | # 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior 8 | # 9 | # 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution 10 | # (no-op if database is already initialized) 11 | # 12 | # 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use 13 | # (error if database is already initialized) 14 | # 15 | 16 | source /usr/local/bin/docker-entrypoint.sh 17 | 18 | # arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) 19 | if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then 20 | set -- postgres "$@" 21 | fi 22 | 23 | # see also "_main" in "docker-entrypoint.sh" 24 | 25 | docker_setup_env 26 | # setup data directories and permissions (when run as root) 27 | docker_create_db_directories 28 | if [ "$(id -u)" = '0' ]; then 29 | # then restart script as postgres user 30 | exec gosu postgres "$BASH_SOURCE" "$@" 31 | fi 32 | 33 | # only run initialization on an empty data directory 34 | if [ -z "$DATABASE_ALREADY_EXISTS" ]; then 35 | docker_verify_minimum_env 36 | 37 | # check dir permissions to reduce likelihood of half-initialized database 38 | ls /docker-entrypoint-initdb.d/ > /dev/null 39 | 40 | docker_init_database_dir 41 | pg_setup_hba_conf "$@" 42 | 43 | # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless 44 | # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS 45 | export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" 46 | docker_temp_server_start "$@" 47 | 48 | docker_setup_db 49 | docker_process_init_files /docker-entrypoint-initdb.d/* 50 | 51 | docker_temp_server_stop 52 | unset PGPASSWORD 53 | else 54 | self="$(basename "$0")" 55 | case "$self" in 56 | docker-ensure-initdb.sh) 57 | echo >&2 "$self: note: database already initialized in '$PGDATA'!" 58 | exit 0 59 | ;; 60 | 61 | docker-enforce-initdb.sh) 62 | echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" 63 | exit 1 64 | ;; 65 | 66 | *) 67 | echo >&2 "$self: error: unknown file name: $self" 68 | exit 99 69 | ;; 70 | esac 71 | fi 72 | -------------------------------------------------------------------------------- /16/alpine3.22/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" 3 | # 4 | # PLEASE DO NOT EDIT IT DIRECTLY. 5 | # 6 | 7 | FROM alpine:3.22 8 | 9 | # 70 is the standard uid/gid for "postgres" in Alpine 10 | # https://git.alpinelinux.org/aports/tree/main/postgresql-common/postgresql-common.pre-install?h=3.22-stable 11 | RUN set -eux; \ 12 | addgroup -g 70 -S postgres; \ 13 | adduser -u 70 -S -D -G postgres -H -h /var/lib/postgresql -s /bin/sh postgres; \ 14 | # also create the postgres user's home directory with appropriate permissions 15 | # see https://github.com/docker-library/postgres/issues/274 16 | install --verbose --directory --owner postgres --group postgres --mode 1777 /var/lib/postgresql 17 | 18 | # grab gosu for easy step-down from root 19 | # https://github.com/tianon/gosu/releases 20 | ENV GOSU_VERSION 1.17 21 | RUN set -eux; \ 22 | \ 23 | apk add --no-cache --virtual .gosu-deps \ 24 | ca-certificates \ 25 | dpkg \ 26 | gnupg \ 27 | ; \ 28 | \ 29 | dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \ 30 | wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \ 31 | wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \ 32 | \ 33 | # verify the signature 34 | export GNUPGHOME="$(mktemp -d)"; \ 35 | gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ 36 | gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \ 37 | gpgconf --kill all; \ 38 | rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \ 39 | \ 40 | # clean up fetch dependencies 41 | apk del --no-network .gosu-deps; \ 42 | \ 43 | chmod +x /usr/local/bin/gosu; \ 44 | # verify that the binary works 45 | gosu --version; \ 46 | gosu nobody true 47 | RUN set -eux; ln -svf gosu /usr/local/bin/su-exec; su-exec nobody true # backwards compatibility (removed in PostgreSQL 17+) 48 | 49 | # make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default 50 | # alpine doesn't require explicit locale-file generation 51 | ENV LANG en_US.utf8 52 | 53 | RUN mkdir /docker-entrypoint-initdb.d 54 | 55 | ENV PG_MAJOR 16 56 | ENV PG_VERSION 16.9 57 | ENV PG_SHA256 07c00fb824df0a0c295f249f44691b86e3266753b380c96f633c3311e10bd005 58 | 59 | ENV DOCKER_PG_LLVM_DEPS \ 60 | llvm19-dev \ 61 | clang19 62 | 63 | RUN set -eux; \ 64 | \ 65 | wget -O postgresql.tar.bz2 "https://ftp.postgresql.org/pub/source/v$PG_VERSION/postgresql-$PG_VERSION.tar.bz2"; \ 66 | echo "$PG_SHA256 *postgresql.tar.bz2" | sha256sum -c -; \ 67 | mkdir -p /usr/src/postgresql; \ 68 | tar \ 69 | --extract \ 70 | --file postgresql.tar.bz2 \ 71 | --directory /usr/src/postgresql \ 72 | --strip-components 1 \ 73 | ; \ 74 | rm postgresql.tar.bz2; \ 75 | \ 76 | apk add --no-cache --virtual .build-deps \ 77 | $DOCKER_PG_LLVM_DEPS \ 78 | bison \ 79 | coreutils \ 80 | dpkg-dev dpkg \ 81 | flex \ 82 | g++ \ 83 | gcc \ 84 | krb5-dev \ 85 | libc-dev \ 86 | libedit-dev \ 87 | libxml2-dev \ 88 | libxslt-dev \ 89 | linux-headers \ 90 | make \ 91 | openldap-dev \ 92 | openssl-dev \ 93 | perl-dev \ 94 | perl-ipc-run \ 95 | perl-utils \ 96 | python3-dev \ 97 | tcl-dev \ 98 | util-linux-dev \ 99 | zlib-dev \ 100 | # https://www.postgresql.org/docs/10/static/release-10.html#id-1.11.6.9.5.13 101 | icu-dev \ 102 | # https://www.postgresql.org/docs/14/release-14.html#id-1.11.6.5.5.3.7 103 | lz4-dev \ 104 | # https://www.postgresql.org/docs/15/release-15.html "--with-zstd to enable Zstandard builds" 105 | zstd-dev \ 106 | ; \ 107 | \ 108 | cd /usr/src/postgresql; \ 109 | # update "DEFAULT_PGSOCKET_DIR" to "/var/run/postgresql" (matching Debian) 110 | # see https://anonscm.debian.org/git/pkg-postgresql/postgresql.git/tree/debian/patches/51-default-sockets-in-var.patch?id=8b539fcb3e093a521c095e70bdfa76887217b89f 111 | awk '$1 == "#define" && $2 == "DEFAULT_PGSOCKET_DIR" && $3 == "\"/tmp\"" { $3 = "\"/var/run/postgresql\""; print; next } { print }' src/include/pg_config_manual.h > src/include/pg_config_manual.h.new; \ 112 | grep '/var/run/postgresql' src/include/pg_config_manual.h.new; \ 113 | mv src/include/pg_config_manual.h.new src/include/pg_config_manual.h; \ 114 | gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \ 115 | \ 116 | # https://git.alpinelinux.org/aports/tree/community/postgresql15/APKBUILD?h=3.22-stable#n176 ("export LLVM_CONFIG") 117 | export LLVM_CONFIG="/usr/lib/llvm19/bin/llvm-config"; \ 118 | # https://git.alpinelinux.org/aports/tree/community/postgresql15/APKBUILD?h=3.22-stable#n180 ("older clang versions don't have a 'clang' exe anymore.") 119 | export CLANG=clang-19; \ 120 | \ 121 | # configure options taken from: 122 | # https://anonscm.debian.org/cgit/pkg-postgresql/postgresql.git/tree/debian/rules?h=9.5 123 | ./configure \ 124 | --enable-option-checking=fatal \ 125 | --build="$gnuArch" \ 126 | # "/usr/src/postgresql/src/backend/access/common/tupconvert.c:105: undefined reference to `libintl_gettext'" 127 | # --enable-nls \ 128 | --enable-integer-datetimes \ 129 | --enable-thread-safety \ 130 | --enable-tap-tests \ 131 | # skip debugging info -- we want tiny size instead 132 | # --enable-debug \ 133 | --disable-rpath \ 134 | --with-uuid=e2fs \ 135 | --with-pgport=5432 \ 136 | --with-system-tzdata=/usr/share/zoneinfo \ 137 | --prefix=/usr/local \ 138 | --with-includes=/usr/local/include \ 139 | --with-libraries=/usr/local/lib \ 140 | --with-gssapi \ 141 | --with-ldap \ 142 | --with-tcl \ 143 | --with-perl \ 144 | --with-python \ 145 | # --with-pam \ 146 | --with-openssl \ 147 | --with-libxml \ 148 | --with-libxslt \ 149 | --with-icu \ 150 | --with-llvm \ 151 | --with-lz4 \ 152 | --with-zstd \ 153 | ; \ 154 | make -j "$(nproc)" world-bin; \ 155 | make install-world-bin; \ 156 | make -C contrib install; \ 157 | \ 158 | runDeps="$( \ 159 | scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \ 160 | | tr ',' '\n' \ 161 | | sort -u \ 162 | | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ 163 | # Remove plperl, plpython and pltcl dependencies by default to save image size 164 | # To use the pl extensions, those have to be installed in a derived image 165 | | grep -v -e perl -e python -e tcl \ 166 | )"; \ 167 | apk add --no-cache --virtual .postgresql-rundeps \ 168 | $runDeps \ 169 | bash \ 170 | tzdata \ 171 | zstd \ 172 | # https://wiki.alpinelinux.org/wiki/Release_Notes_for_Alpine_3.16.0#ICU_data_split 173 | icu-data-full \ 174 | # https://git.alpinelinux.org/aports/tree/community/nss_wrapper/APKBUILD?h=3.22-stable#n7 ("ppc64le: test case segfaults") 175 | $([ "$(apk --print-arch)" != 'ppc64le' ] && echo 'nss_wrapper') \ 176 | ; \ 177 | apk del --no-network .build-deps; \ 178 | cd /; \ 179 | rm -rf \ 180 | /usr/src/postgresql \ 181 | /usr/local/share/doc \ 182 | /usr/local/share/man \ 183 | ; \ 184 | \ 185 | postgres --version 186 | 187 | # make the sample config easier to munge (and "correct by default") 188 | RUN set -eux; \ 189 | cp -v /usr/local/share/postgresql/postgresql.conf.sample /usr/local/share/postgresql/postgresql.conf.sample.orig; \ 190 | sed -ri "s!^#?(listen_addresses)\s*=\s*\S+.*!\1 = '*'!" /usr/local/share/postgresql/postgresql.conf.sample; \ 191 | grep -F "listen_addresses = '*'" /usr/local/share/postgresql/postgresql.conf.sample 192 | 193 | RUN install --verbose --directory --owner postgres --group postgres --mode 3777 /var/run/postgresql 194 | 195 | ENV PGDATA /var/lib/postgresql/data 196 | # this 1777 will be replaced by 0700 at runtime (allows semi-arbitrary "--user" values) 197 | RUN install --verbose --directory --owner postgres --group postgres --mode 1777 "$PGDATA" 198 | VOLUME /var/lib/postgresql/data 199 | 200 | COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ 201 | RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh 202 | ENTRYPOINT ["docker-entrypoint.sh"] 203 | 204 | # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL 205 | # calls "Fast Shutdown mode" wherein new connections are disallowed and any 206 | # in-progress transactions are aborted, allowing PostgreSQL to stop cleanly and 207 | # flush tables to disk. 208 | # 209 | # See https://www.postgresql.org/docs/current/server-shutdown.html for more details 210 | # about available PostgreSQL server shutdown signals. 211 | # 212 | # See also https://www.postgresql.org/docs/current/server-start.html for further 213 | # justification of this as the default value, namely that the example (and 214 | # shipped) systemd service files use the "Fast Shutdown mode" for service 215 | # termination. 216 | # 217 | STOPSIGNAL SIGINT 218 | # 219 | # An additional setting that is recommended for all users regardless of this 220 | # value is the runtime "--stop-timeout" (or your orchestrator/runtime's 221 | # equivalent) for controlling how long to wait between sending the defined 222 | # STOPSIGNAL and sending SIGKILL. 223 | # 224 | # The default in most runtimes (such as Docker) is 10 seconds, and the 225 | # documentation at https://www.postgresql.org/docs/current/server-start.html notes 226 | # that even 90 seconds may not be long enough in many instances. 227 | 228 | EXPOSE 5432 229 | CMD ["postgres"] 230 | -------------------------------------------------------------------------------- /16/alpine3.22/docker-ensure-initdb.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | # 5 | # This script is intended for three main use cases: 6 | # 7 | # 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior 8 | # 9 | # 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution 10 | # (no-op if database is already initialized) 11 | # 12 | # 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use 13 | # (error if database is already initialized) 14 | # 15 | 16 | source /usr/local/bin/docker-entrypoint.sh 17 | 18 | # arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) 19 | if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then 20 | set -- postgres "$@" 21 | fi 22 | 23 | # see also "_main" in "docker-entrypoint.sh" 24 | 25 | docker_setup_env 26 | # setup data directories and permissions (when run as root) 27 | docker_create_db_directories 28 | if [ "$(id -u)" = '0' ]; then 29 | # then restart script as postgres user 30 | exec gosu postgres "$BASH_SOURCE" "$@" 31 | fi 32 | 33 | # only run initialization on an empty data directory 34 | if [ -z "$DATABASE_ALREADY_EXISTS" ]; then 35 | docker_verify_minimum_env 36 | 37 | # check dir permissions to reduce likelihood of half-initialized database 38 | ls /docker-entrypoint-initdb.d/ > /dev/null 39 | 40 | docker_init_database_dir 41 | pg_setup_hba_conf "$@" 42 | 43 | # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless 44 | # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS 45 | export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" 46 | docker_temp_server_start "$@" 47 | 48 | docker_setup_db 49 | docker_process_init_files /docker-entrypoint-initdb.d/* 50 | 51 | docker_temp_server_stop 52 | unset PGPASSWORD 53 | else 54 | self="$(basename "$0")" 55 | case "$self" in 56 | docker-ensure-initdb.sh) 57 | echo >&2 "$self: note: database already initialized in '$PGDATA'!" 58 | exit 0 59 | ;; 60 | 61 | docker-enforce-initdb.sh) 62 | echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" 63 | exit 1 64 | ;; 65 | 66 | *) 67 | echo >&2 "$self: error: unknown file name: $self" 68 | exit 99 69 | ;; 70 | esac 71 | fi 72 | -------------------------------------------------------------------------------- /16/bookworm/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" 3 | # 4 | # PLEASE DO NOT EDIT IT DIRECTLY. 5 | # 6 | 7 | FROM debian:bookworm-slim 8 | 9 | # explicitly set user/group IDs 10 | RUN set -eux; \ 11 | groupadd -r postgres --gid=999; \ 12 | # https://salsa.debian.org/postgresql/postgresql-common/blob/997d842ee744687d99a2b2d95c1083a2615c79e8/debian/postgresql-common.postinst#L32-35 13 | useradd -r -g postgres --uid=999 --home-dir=/var/lib/postgresql --shell=/bin/bash postgres; \ 14 | # also create the postgres user's home directory with appropriate permissions 15 | # see https://github.com/docker-library/postgres/issues/274 16 | install --verbose --directory --owner postgres --group postgres --mode 1777 /var/lib/postgresql 17 | 18 | RUN set -ex; \ 19 | apt-get update; \ 20 | apt-get install -y --no-install-recommends \ 21 | gnupg \ 22 | # https://www.postgresql.org/docs/16/app-psql.html#APP-PSQL-META-COMMAND-PSET-PAGER 23 | # https://github.com/postgres/postgres/blob/REL_16_1/src/include/fe_utils/print.h#L25 24 | # (if "less" is available, it gets used as the default pager for psql, and it only adds ~1.5MiB to our image size) 25 | less \ 26 | ; \ 27 | rm -rf /var/lib/apt/lists/* 28 | 29 | # grab gosu for easy step-down from root 30 | # https://github.com/tianon/gosu/releases 31 | ENV GOSU_VERSION 1.17 32 | RUN set -eux; \ 33 | savedAptMark="$(apt-mark showmanual)"; \ 34 | apt-get update; \ 35 | apt-get install -y --no-install-recommends ca-certificates wget; \ 36 | rm -rf /var/lib/apt/lists/*; \ 37 | dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \ 38 | wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \ 39 | wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \ 40 | export GNUPGHOME="$(mktemp -d)"; \ 41 | gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ 42 | gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \ 43 | gpgconf --kill all; \ 44 | rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \ 45 | apt-mark auto '.*' > /dev/null; \ 46 | [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; \ 47 | apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ 48 | chmod +x /usr/local/bin/gosu; \ 49 | gosu --version; \ 50 | gosu nobody true 51 | 52 | # make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default 53 | RUN set -eux; \ 54 | if [ -f /etc/dpkg/dpkg.cfg.d/docker ]; then \ 55 | # if this file exists, we're likely in "debian:xxx-slim", and locales are thus being excluded so we need to remove that exclusion (since we need locales) 56 | grep -q '/usr/share/locale' /etc/dpkg/dpkg.cfg.d/docker; \ 57 | sed -ri '/\/usr\/share\/locale/d' /etc/dpkg/dpkg.cfg.d/docker; \ 58 | ! grep -q '/usr/share/locale' /etc/dpkg/dpkg.cfg.d/docker; \ 59 | fi; \ 60 | apt-get update; apt-get install -y --no-install-recommends locales; rm -rf /var/lib/apt/lists/*; \ 61 | echo 'en_US.UTF-8 UTF-8' >> /etc/locale.gen; \ 62 | locale-gen; \ 63 | locale -a | grep 'en_US.utf8' 64 | ENV LANG en_US.utf8 65 | 66 | RUN set -eux; \ 67 | apt-get update; \ 68 | apt-get install -y --no-install-recommends \ 69 | libnss-wrapper \ 70 | xz-utils \ 71 | zstd \ 72 | ; \ 73 | rm -rf /var/lib/apt/lists/* 74 | 75 | RUN mkdir /docker-entrypoint-initdb.d 76 | 77 | RUN set -ex; \ 78 | # pub 4096R/ACCC4CF8 2011-10-13 [expires: 2019-07-02] 79 | # Key fingerprint = B97B 0AFC AA1A 47F0 44F2 44A0 7FCC 7D46 ACCC 4CF8 80 | # uid PostgreSQL Debian Repository 81 | key='B97B0AFCAA1A47F044F244A07FCC7D46ACCC4CF8'; \ 82 | export GNUPGHOME="$(mktemp -d)"; \ 83 | mkdir -p /usr/local/share/keyrings/; \ 84 | gpg --batch --keyserver keyserver.ubuntu.com --recv-keys "$key"; \ 85 | gpg --batch --export --armor "$key" > /usr/local/share/keyrings/postgres.gpg.asc; \ 86 | gpgconf --kill all; \ 87 | rm -rf "$GNUPGHOME" 88 | 89 | ENV PG_MAJOR 16 90 | ENV PATH $PATH:/usr/lib/postgresql/$PG_MAJOR/bin 91 | 92 | ENV PG_VERSION 16.9-1.pgdg120+1 93 | 94 | RUN set -ex; \ 95 | \ 96 | # see note below about "*.pyc" files 97 | export PYTHONDONTWRITEBYTECODE=1; \ 98 | \ 99 | dpkgArch="$(dpkg --print-architecture)"; \ 100 | aptRepo="[ signed-by=/usr/local/share/keyrings/postgres.gpg.asc ] http://apt.postgresql.org/pub/repos/apt/ bookworm-pgdg main $PG_MAJOR"; \ 101 | case "$dpkgArch" in \ 102 | amd64 | arm64 | ppc64el) \ 103 | # arches officialy built by upstream 104 | echo "deb $aptRepo" > /etc/apt/sources.list.d/pgdg.list; \ 105 | apt-get update; \ 106 | ;; \ 107 | *) \ 108 | # we're on an architecture upstream doesn't officially build for 109 | # let's build binaries from their published source packages 110 | echo "deb-src $aptRepo" > /etc/apt/sources.list.d/pgdg.list; \ 111 | \ 112 | savedAptMark="$(apt-mark showmanual)"; \ 113 | \ 114 | tempDir="$(mktemp -d)"; \ 115 | cd "$tempDir"; \ 116 | \ 117 | # create a temporary local APT repo to install from (so that dependency resolution can be handled by APT, as it should be) 118 | apt-get update; \ 119 | apt-get install -y --no-install-recommends dpkg-dev; \ 120 | echo "deb [ trusted=yes ] file://$tempDir ./" > /etc/apt/sources.list.d/temp.list; \ 121 | _update_repo() { \ 122 | dpkg-scanpackages . > Packages; \ 123 | # work around the following APT issue by using "Acquire::GzipIndexes=false" (overriding "/etc/apt/apt.conf.d/docker-gzip-indexes") 124 | # Could not open file /var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages - open (13: Permission denied) 125 | # ... 126 | # E: Failed to fetch store:/var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages Could not open file /var/lib/apt/lists/partial/_tmp_tmp.ODWljpQfkE_._Packages - open (13: Permission denied) 127 | apt-get -o Acquire::GzipIndexes=false update; \ 128 | }; \ 129 | _update_repo; \ 130 | \ 131 | # build .deb files from upstream's source packages (which are verified by apt-get) 132 | nproc="$(nproc)"; \ 133 | export DEB_BUILD_OPTIONS="nocheck parallel=$nproc"; \ 134 | # we have to build postgresql-common-dev first because postgresql-$PG_MAJOR shares "debian/rules" logic with it: https://salsa.debian.org/postgresql/postgresql/-/commit/f4338a0d28cf4541956bddb0f4e444ba9dba81b9 135 | apt-get build-dep -y postgresql-common-dev; \ 136 | apt-get source --compile postgresql-common-dev; \ 137 | _update_repo; \ 138 | apt-get build-dep -y "postgresql-$PG_MAJOR=$PG_VERSION"; \ 139 | apt-get source --compile "postgresql-$PG_MAJOR=$PG_VERSION"; \ 140 | \ 141 | # we don't remove APT lists here because they get re-downloaded and removed later 142 | \ 143 | # reset apt-mark's "manual" list so that "purge --auto-remove" will remove all build dependencies 144 | # (which is done after we install the built packages so we don't have to redownload any overlapping dependencies) 145 | apt-mark showmanual | xargs apt-mark auto > /dev/null; \ 146 | apt-mark manual $savedAptMark; \ 147 | \ 148 | ls -lAFh; \ 149 | _update_repo; \ 150 | grep '^Package: ' Packages; \ 151 | cd /; \ 152 | ;; \ 153 | esac; \ 154 | \ 155 | apt-get install -y --no-install-recommends postgresql-common; \ 156 | sed -ri 's/#(create_main_cluster) .*$/\1 = false/' /etc/postgresql-common/createcluster.conf; \ 157 | apt-get install -y --no-install-recommends \ 158 | "postgresql-$PG_MAJOR=$PG_VERSION" \ 159 | ; \ 160 | \ 161 | rm -rf /var/lib/apt/lists/*; \ 162 | \ 163 | if [ -n "$tempDir" ]; then \ 164 | # if we have leftovers from building, let's purge them (including extra, unnecessary build deps) 165 | apt-get purge -y --auto-remove; \ 166 | rm -rf "$tempDir" /etc/apt/sources.list.d/temp.list; \ 167 | fi; \ 168 | \ 169 | # some of the steps above generate a lot of "*.pyc" files (and setting "PYTHONDONTWRITEBYTECODE" beforehand doesn't propagate properly for some reason), so we clean them up manually (as long as they aren't owned by a package) 170 | find /usr -name '*.pyc' -type f -exec bash -c 'for pyc; do dpkg -S "$pyc" &> /dev/null || rm -vf "$pyc"; done' -- '{}' +; \ 171 | \ 172 | postgres --version 173 | 174 | # make the sample config easier to munge (and "correct by default") 175 | RUN set -eux; \ 176 | dpkg-divert --add --rename --divert "/usr/share/postgresql/postgresql.conf.sample.dpkg" "/usr/share/postgresql/$PG_MAJOR/postgresql.conf.sample"; \ 177 | cp -v /usr/share/postgresql/postgresql.conf.sample.dpkg /usr/share/postgresql/postgresql.conf.sample; \ 178 | ln -sv ../postgresql.conf.sample "/usr/share/postgresql/$PG_MAJOR/"; \ 179 | sed -ri "s!^#?(listen_addresses)\s*=\s*\S+.*!\1 = '*'!" /usr/share/postgresql/postgresql.conf.sample; \ 180 | grep -F "listen_addresses = '*'" /usr/share/postgresql/postgresql.conf.sample 181 | 182 | RUN install --verbose --directory --owner postgres --group postgres --mode 3777 /var/run/postgresql 183 | 184 | ENV PGDATA /var/lib/postgresql/data 185 | # this 1777 will be replaced by 0700 at runtime (allows semi-arbitrary "--user" values) 186 | RUN install --verbose --directory --owner postgres --group postgres --mode 1777 "$PGDATA" 187 | VOLUME /var/lib/postgresql/data 188 | 189 | COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ 190 | RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh 191 | ENTRYPOINT ["docker-entrypoint.sh"] 192 | 193 | # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL 194 | # calls "Fast Shutdown mode" wherein new connections are disallowed and any 195 | # in-progress transactions are aborted, allowing PostgreSQL to stop cleanly and 196 | # flush tables to disk. 197 | # 198 | # See https://www.postgresql.org/docs/current/server-shutdown.html for more details 199 | # about available PostgreSQL server shutdown signals. 200 | # 201 | # See also https://www.postgresql.org/docs/current/server-start.html for further 202 | # justification of this as the default value, namely that the example (and 203 | # shipped) systemd service files use the "Fast Shutdown mode" for service 204 | # termination. 205 | # 206 | STOPSIGNAL SIGINT 207 | # 208 | # An additional setting that is recommended for all users regardless of this 209 | # value is the runtime "--stop-timeout" (or your orchestrator/runtime's 210 | # equivalent) for controlling how long to wait between sending the defined 211 | # STOPSIGNAL and sending SIGKILL. 212 | # 213 | # The default in most runtimes (such as Docker) is 10 seconds, and the 214 | # documentation at https://www.postgresql.org/docs/current/server-start.html notes 215 | # that even 90 seconds may not be long enough in many instances. 216 | 217 | EXPOSE 5432 218 | CMD ["postgres"] 219 | -------------------------------------------------------------------------------- /16/bookworm/docker-ensure-initdb.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | # 5 | # This script is intended for three main use cases: 6 | # 7 | # 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior 8 | # 9 | # 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution 10 | # (no-op if database is already initialized) 11 | # 12 | # 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use 13 | # (error if database is already initialized) 14 | # 15 | 16 | source /usr/local/bin/docker-entrypoint.sh 17 | 18 | # arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) 19 | if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then 20 | set -- postgres "$@" 21 | fi 22 | 23 | # see also "_main" in "docker-entrypoint.sh" 24 | 25 | docker_setup_env 26 | # setup data directories and permissions (when run as root) 27 | docker_create_db_directories 28 | if [ "$(id -u)" = '0' ]; then 29 | # then restart script as postgres user 30 | exec gosu postgres "$BASH_SOURCE" "$@" 31 | fi 32 | 33 | # only run initialization on an empty data directory 34 | if [ -z "$DATABASE_ALREADY_EXISTS" ]; then 35 | docker_verify_minimum_env 36 | 37 | # check dir permissions to reduce likelihood of half-initialized database 38 | ls /docker-entrypoint-initdb.d/ > /dev/null 39 | 40 | docker_init_database_dir 41 | pg_setup_hba_conf "$@" 42 | 43 | # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless 44 | # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS 45 | export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" 46 | docker_temp_server_start "$@" 47 | 48 | docker_setup_db 49 | docker_process_init_files /docker-entrypoint-initdb.d/* 50 | 51 | docker_temp_server_stop 52 | unset PGPASSWORD 53 | else 54 | self="$(basename "$0")" 55 | case "$self" in 56 | docker-ensure-initdb.sh) 57 | echo >&2 "$self: note: database already initialized in '$PGDATA'!" 58 | exit 0 59 | ;; 60 | 61 | docker-enforce-initdb.sh) 62 | echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" 63 | exit 1 64 | ;; 65 | 66 | *) 67 | echo >&2 "$self: error: unknown file name: $self" 68 | exit 99 69 | ;; 70 | esac 71 | fi 72 | -------------------------------------------------------------------------------- /16/bullseye/docker-ensure-initdb.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | # 5 | # This script is intended for three main use cases: 6 | # 7 | # 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior 8 | # 9 | # 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution 10 | # (no-op if database is already initialized) 11 | # 12 | # 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use 13 | # (error if database is already initialized) 14 | # 15 | 16 | source /usr/local/bin/docker-entrypoint.sh 17 | 18 | # arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) 19 | if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then 20 | set -- postgres "$@" 21 | fi 22 | 23 | # see also "_main" in "docker-entrypoint.sh" 24 | 25 | docker_setup_env 26 | # setup data directories and permissions (when run as root) 27 | docker_create_db_directories 28 | if [ "$(id -u)" = '0' ]; then 29 | # then restart script as postgres user 30 | exec gosu postgres "$BASH_SOURCE" "$@" 31 | fi 32 | 33 | # only run initialization on an empty data directory 34 | if [ -z "$DATABASE_ALREADY_EXISTS" ]; then 35 | docker_verify_minimum_env 36 | 37 | # check dir permissions to reduce likelihood of half-initialized database 38 | ls /docker-entrypoint-initdb.d/ > /dev/null 39 | 40 | docker_init_database_dir 41 | pg_setup_hba_conf "$@" 42 | 43 | # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless 44 | # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS 45 | export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" 46 | docker_temp_server_start "$@" 47 | 48 | docker_setup_db 49 | docker_process_init_files /docker-entrypoint-initdb.d/* 50 | 51 | docker_temp_server_stop 52 | unset PGPASSWORD 53 | else 54 | self="$(basename "$0")" 55 | case "$self" in 56 | docker-ensure-initdb.sh) 57 | echo >&2 "$self: note: database already initialized in '$PGDATA'!" 58 | exit 0 59 | ;; 60 | 61 | docker-enforce-initdb.sh) 62 | echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" 63 | exit 1 64 | ;; 65 | 66 | *) 67 | echo >&2 "$self: error: unknown file name: $self" 68 | exit 99 69 | ;; 70 | esac 71 | fi 72 | -------------------------------------------------------------------------------- /17/alpine3.21/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" 3 | # 4 | # PLEASE DO NOT EDIT IT DIRECTLY. 5 | # 6 | 7 | FROM alpine:3.21 8 | 9 | # 70 is the standard uid/gid for "postgres" in Alpine 10 | # https://git.alpinelinux.org/aports/tree/main/postgresql-common/postgresql-common.pre-install?h=3.22-stable 11 | RUN set -eux; \ 12 | addgroup -g 70 -S postgres; \ 13 | adduser -u 70 -S -D -G postgres -H -h /var/lib/postgresql -s /bin/sh postgres; \ 14 | # also create the postgres user's home directory with appropriate permissions 15 | # see https://github.com/docker-library/postgres/issues/274 16 | install --verbose --directory --owner postgres --group postgres --mode 1777 /var/lib/postgresql 17 | 18 | # grab gosu for easy step-down from root 19 | # https://github.com/tianon/gosu/releases 20 | ENV GOSU_VERSION 1.17 21 | RUN set -eux; \ 22 | \ 23 | apk add --no-cache --virtual .gosu-deps \ 24 | ca-certificates \ 25 | dpkg \ 26 | gnupg \ 27 | ; \ 28 | \ 29 | dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \ 30 | wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \ 31 | wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \ 32 | \ 33 | # verify the signature 34 | export GNUPGHOME="$(mktemp -d)"; \ 35 | gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ 36 | gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \ 37 | gpgconf --kill all; \ 38 | rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \ 39 | \ 40 | # clean up fetch dependencies 41 | apk del --no-network .gosu-deps; \ 42 | \ 43 | chmod +x /usr/local/bin/gosu; \ 44 | # verify that the binary works 45 | gosu --version; \ 46 | gosu nobody true 47 | 48 | # make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default 49 | # alpine doesn't require explicit locale-file generation 50 | ENV LANG en_US.utf8 51 | 52 | RUN mkdir /docker-entrypoint-initdb.d 53 | 54 | ENV PG_MAJOR 17 55 | ENV PG_VERSION 17.5 56 | ENV PG_SHA256 fcb7ab38e23b264d1902cb25e6adafb4525a6ebcbd015434aeef9eda80f528d8 57 | 58 | ENV DOCKER_PG_LLVM_DEPS \ 59 | llvm19-dev \ 60 | clang19 61 | 62 | RUN set -eux; \ 63 | \ 64 | wget -O postgresql.tar.bz2 "https://ftp.postgresql.org/pub/source/v$PG_VERSION/postgresql-$PG_VERSION.tar.bz2"; \ 65 | echo "$PG_SHA256 *postgresql.tar.bz2" | sha256sum -c -; \ 66 | mkdir -p /usr/src/postgresql; \ 67 | tar \ 68 | --extract \ 69 | --file postgresql.tar.bz2 \ 70 | --directory /usr/src/postgresql \ 71 | --strip-components 1 \ 72 | ; \ 73 | rm postgresql.tar.bz2; \ 74 | \ 75 | apk add --no-cache --virtual .build-deps \ 76 | $DOCKER_PG_LLVM_DEPS \ 77 | bison \ 78 | coreutils \ 79 | dpkg-dev dpkg \ 80 | flex \ 81 | g++ \ 82 | gcc \ 83 | krb5-dev \ 84 | libc-dev \ 85 | libedit-dev \ 86 | libxml2-dev \ 87 | libxslt-dev \ 88 | linux-headers \ 89 | make \ 90 | openldap-dev \ 91 | openssl-dev \ 92 | perl-dev \ 93 | perl-ipc-run \ 94 | perl-utils \ 95 | python3-dev \ 96 | tcl-dev \ 97 | util-linux-dev \ 98 | zlib-dev \ 99 | # https://www.postgresql.org/docs/10/static/release-10.html#id-1.11.6.9.5.13 100 | icu-dev \ 101 | # https://www.postgresql.org/docs/14/release-14.html#id-1.11.6.5.5.3.7 102 | lz4-dev \ 103 | # https://www.postgresql.org/docs/15/release-15.html "--with-zstd to enable Zstandard builds" 104 | zstd-dev \ 105 | ; \ 106 | \ 107 | cd /usr/src/postgresql; \ 108 | # update "DEFAULT_PGSOCKET_DIR" to "/var/run/postgresql" (matching Debian) 109 | # see https://anonscm.debian.org/git/pkg-postgresql/postgresql.git/tree/debian/patches/51-default-sockets-in-var.patch?id=8b539fcb3e093a521c095e70bdfa76887217b89f 110 | awk '$1 == "#define" && $2 == "DEFAULT_PGSOCKET_DIR" && $3 == "\"/tmp\"" { $3 = "\"/var/run/postgresql\""; print; next } { print }' src/include/pg_config_manual.h > src/include/pg_config_manual.h.new; \ 111 | grep '/var/run/postgresql' src/include/pg_config_manual.h.new; \ 112 | mv src/include/pg_config_manual.h.new src/include/pg_config_manual.h; \ 113 | gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \ 114 | \ 115 | # https://git.alpinelinux.org/aports/tree/community/postgresql15/APKBUILD?h=3.22-stable#n176 ("export LLVM_CONFIG") 116 | export LLVM_CONFIG="/usr/lib/llvm19/bin/llvm-config"; \ 117 | # https://git.alpinelinux.org/aports/tree/community/postgresql15/APKBUILD?h=3.22-stable#n180 ("older clang versions don't have a 'clang' exe anymore.") 118 | export CLANG=clang-19; \ 119 | \ 120 | # configure options taken from: 121 | # https://anonscm.debian.org/cgit/pkg-postgresql/postgresql.git/tree/debian/rules?h=9.5 122 | ./configure \ 123 | --enable-option-checking=fatal \ 124 | --build="$gnuArch" \ 125 | # "/usr/src/postgresql/src/backend/access/common/tupconvert.c:105: undefined reference to `libintl_gettext'" 126 | # --enable-nls \ 127 | --enable-integer-datetimes \ 128 | --enable-tap-tests \ 129 | # skip debugging info -- we want tiny size instead 130 | # --enable-debug \ 131 | --disable-rpath \ 132 | --with-uuid=e2fs \ 133 | --with-pgport=5432 \ 134 | --with-system-tzdata=/usr/share/zoneinfo \ 135 | --prefix=/usr/local \ 136 | --with-includes=/usr/local/include \ 137 | --with-libraries=/usr/local/lib \ 138 | --with-gssapi \ 139 | --with-ldap \ 140 | --with-tcl \ 141 | --with-perl \ 142 | --with-python \ 143 | # --with-pam \ 144 | --with-openssl \ 145 | --with-libxml \ 146 | --with-libxslt \ 147 | --with-icu \ 148 | --with-llvm \ 149 | --with-lz4 \ 150 | --with-zstd \ 151 | ; \ 152 | make -j "$(nproc)" world-bin; \ 153 | make install-world-bin; \ 154 | make -C contrib install; \ 155 | \ 156 | runDeps="$( \ 157 | scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \ 158 | | tr ',' '\n' \ 159 | | sort -u \ 160 | | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ 161 | # Remove plperl, plpython and pltcl dependencies by default to save image size 162 | # To use the pl extensions, those have to be installed in a derived image 163 | | grep -v -e perl -e python -e tcl \ 164 | )"; \ 165 | apk add --no-cache --virtual .postgresql-rundeps \ 166 | $runDeps \ 167 | bash \ 168 | tzdata \ 169 | zstd \ 170 | # https://wiki.alpinelinux.org/wiki/Release_Notes_for_Alpine_3.16.0#ICU_data_split 171 | icu-data-full \ 172 | # https://git.alpinelinux.org/aports/tree/community/nss_wrapper/APKBUILD?h=3.22-stable#n7 ("ppc64le: test case segfaults") 173 | $([ "$(apk --print-arch)" != 'ppc64le' ] && echo 'nss_wrapper') \ 174 | ; \ 175 | apk del --no-network .build-deps; \ 176 | cd /; \ 177 | rm -rf \ 178 | /usr/src/postgresql \ 179 | /usr/local/share/doc \ 180 | /usr/local/share/man \ 181 | ; \ 182 | \ 183 | postgres --version 184 | 185 | # make the sample config easier to munge (and "correct by default") 186 | RUN set -eux; \ 187 | cp -v /usr/local/share/postgresql/postgresql.conf.sample /usr/local/share/postgresql/postgresql.conf.sample.orig; \ 188 | sed -ri "s!^#?(listen_addresses)\s*=\s*\S+.*!\1 = '*'!" /usr/local/share/postgresql/postgresql.conf.sample; \ 189 | grep -F "listen_addresses = '*'" /usr/local/share/postgresql/postgresql.conf.sample 190 | 191 | RUN install --verbose --directory --owner postgres --group postgres --mode 3777 /var/run/postgresql 192 | 193 | ENV PGDATA /var/lib/postgresql/data 194 | # this 1777 will be replaced by 0700 at runtime (allows semi-arbitrary "--user" values) 195 | RUN install --verbose --directory --owner postgres --group postgres --mode 1777 "$PGDATA" 196 | VOLUME /var/lib/postgresql/data 197 | 198 | COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ 199 | RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh 200 | ENTRYPOINT ["docker-entrypoint.sh"] 201 | 202 | # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL 203 | # calls "Fast Shutdown mode" wherein new connections are disallowed and any 204 | # in-progress transactions are aborted, allowing PostgreSQL to stop cleanly and 205 | # flush tables to disk. 206 | # 207 | # See https://www.postgresql.org/docs/current/server-shutdown.html for more details 208 | # about available PostgreSQL server shutdown signals. 209 | # 210 | # See also https://www.postgresql.org/docs/current/server-start.html for further 211 | # justification of this as the default value, namely that the example (and 212 | # shipped) systemd service files use the "Fast Shutdown mode" for service 213 | # termination. 214 | # 215 | STOPSIGNAL SIGINT 216 | # 217 | # An additional setting that is recommended for all users regardless of this 218 | # value is the runtime "--stop-timeout" (or your orchestrator/runtime's 219 | # equivalent) for controlling how long to wait between sending the defined 220 | # STOPSIGNAL and sending SIGKILL. 221 | # 222 | # The default in most runtimes (such as Docker) is 10 seconds, and the 223 | # documentation at https://www.postgresql.org/docs/current/server-start.html notes 224 | # that even 90 seconds may not be long enough in many instances. 225 | 226 | EXPOSE 5432 227 | CMD ["postgres"] 228 | -------------------------------------------------------------------------------- /17/alpine3.21/docker-ensure-initdb.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | # 5 | # This script is intended for three main use cases: 6 | # 7 | # 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior 8 | # 9 | # 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution 10 | # (no-op if database is already initialized) 11 | # 12 | # 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use 13 | # (error if database is already initialized) 14 | # 15 | 16 | source /usr/local/bin/docker-entrypoint.sh 17 | 18 | # arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) 19 | if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then 20 | set -- postgres "$@" 21 | fi 22 | 23 | # see also "_main" in "docker-entrypoint.sh" 24 | 25 | docker_setup_env 26 | # setup data directories and permissions (when run as root) 27 | docker_create_db_directories 28 | if [ "$(id -u)" = '0' ]; then 29 | # then restart script as postgres user 30 | exec gosu postgres "$BASH_SOURCE" "$@" 31 | fi 32 | 33 | # only run initialization on an empty data directory 34 | if [ -z "$DATABASE_ALREADY_EXISTS" ]; then 35 | docker_verify_minimum_env 36 | 37 | # check dir permissions to reduce likelihood of half-initialized database 38 | ls /docker-entrypoint-initdb.d/ > /dev/null 39 | 40 | docker_init_database_dir 41 | pg_setup_hba_conf "$@" 42 | 43 | # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless 44 | # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS 45 | export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" 46 | docker_temp_server_start "$@" 47 | 48 | docker_setup_db 49 | docker_process_init_files /docker-entrypoint-initdb.d/* 50 | 51 | docker_temp_server_stop 52 | unset PGPASSWORD 53 | else 54 | self="$(basename "$0")" 55 | case "$self" in 56 | docker-ensure-initdb.sh) 57 | echo >&2 "$self: note: database already initialized in '$PGDATA'!" 58 | exit 0 59 | ;; 60 | 61 | docker-enforce-initdb.sh) 62 | echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" 63 | exit 1 64 | ;; 65 | 66 | *) 67 | echo >&2 "$self: error: unknown file name: $self" 68 | exit 99 69 | ;; 70 | esac 71 | fi 72 | -------------------------------------------------------------------------------- /17/alpine3.22/Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" 3 | # 4 | # PLEASE DO NOT EDIT IT DIRECTLY. 5 | # 6 | 7 | FROM alpine:3.22 8 | 9 | # 70 is the standard uid/gid for "postgres" in Alpine 10 | # https://git.alpinelinux.org/aports/tree/main/postgresql-common/postgresql-common.pre-install?h=3.22-stable 11 | RUN set -eux; \ 12 | addgroup -g 70 -S postgres; \ 13 | adduser -u 70 -S -D -G postgres -H -h /var/lib/postgresql -s /bin/sh postgres; \ 14 | # also create the postgres user's home directory with appropriate permissions 15 | # see https://github.com/docker-library/postgres/issues/274 16 | install --verbose --directory --owner postgres --group postgres --mode 1777 /var/lib/postgresql 17 | 18 | # grab gosu for easy step-down from root 19 | # https://github.com/tianon/gosu/releases 20 | ENV GOSU_VERSION 1.17 21 | RUN set -eux; \ 22 | \ 23 | apk add --no-cache --virtual .gosu-deps \ 24 | ca-certificates \ 25 | dpkg \ 26 | gnupg \ 27 | ; \ 28 | \ 29 | dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \ 30 | wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \ 31 | wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \ 32 | \ 33 | # verify the signature 34 | export GNUPGHOME="$(mktemp -d)"; \ 35 | gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ 36 | gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \ 37 | gpgconf --kill all; \ 38 | rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \ 39 | \ 40 | # clean up fetch dependencies 41 | apk del --no-network .gosu-deps; \ 42 | \ 43 | chmod +x /usr/local/bin/gosu; \ 44 | # verify that the binary works 45 | gosu --version; \ 46 | gosu nobody true 47 | 48 | # make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default 49 | # alpine doesn't require explicit locale-file generation 50 | ENV LANG en_US.utf8 51 | 52 | RUN mkdir /docker-entrypoint-initdb.d 53 | 54 | ENV PG_MAJOR 17 55 | ENV PG_VERSION 17.5 56 | ENV PG_SHA256 fcb7ab38e23b264d1902cb25e6adafb4525a6ebcbd015434aeef9eda80f528d8 57 | 58 | ENV DOCKER_PG_LLVM_DEPS \ 59 | llvm19-dev \ 60 | clang19 61 | 62 | RUN set -eux; \ 63 | \ 64 | wget -O postgresql.tar.bz2 "https://ftp.postgresql.org/pub/source/v$PG_VERSION/postgresql-$PG_VERSION.tar.bz2"; \ 65 | echo "$PG_SHA256 *postgresql.tar.bz2" | sha256sum -c -; \ 66 | mkdir -p /usr/src/postgresql; \ 67 | tar \ 68 | --extract \ 69 | --file postgresql.tar.bz2 \ 70 | --directory /usr/src/postgresql \ 71 | --strip-components 1 \ 72 | ; \ 73 | rm postgresql.tar.bz2; \ 74 | \ 75 | apk add --no-cache --virtual .build-deps \ 76 | $DOCKER_PG_LLVM_DEPS \ 77 | bison \ 78 | coreutils \ 79 | dpkg-dev dpkg \ 80 | flex \ 81 | g++ \ 82 | gcc \ 83 | krb5-dev \ 84 | libc-dev \ 85 | libedit-dev \ 86 | libxml2-dev \ 87 | libxslt-dev \ 88 | linux-headers \ 89 | make \ 90 | openldap-dev \ 91 | openssl-dev \ 92 | perl-dev \ 93 | perl-ipc-run \ 94 | perl-utils \ 95 | python3-dev \ 96 | tcl-dev \ 97 | util-linux-dev \ 98 | zlib-dev \ 99 | # https://www.postgresql.org/docs/10/static/release-10.html#id-1.11.6.9.5.13 100 | icu-dev \ 101 | # https://www.postgresql.org/docs/14/release-14.html#id-1.11.6.5.5.3.7 102 | lz4-dev \ 103 | # https://www.postgresql.org/docs/15/release-15.html "--with-zstd to enable Zstandard builds" 104 | zstd-dev \ 105 | ; \ 106 | \ 107 | cd /usr/src/postgresql; \ 108 | # update "DEFAULT_PGSOCKET_DIR" to "/var/run/postgresql" (matching Debian) 109 | # see https://anonscm.debian.org/git/pkg-postgresql/postgresql.git/tree/debian/patches/51-default-sockets-in-var.patch?id=8b539fcb3e093a521c095e70bdfa76887217b89f 110 | awk '$1 == "#define" && $2 == "DEFAULT_PGSOCKET_DIR" && $3 == "\"/tmp\"" { $3 = "\"/var/run/postgresql\""; print; next } { print }' src/include/pg_config_manual.h > src/include/pg_config_manual.h.new; \ 111 | grep '/var/run/postgresql' src/include/pg_config_manual.h.new; \ 112 | mv src/include/pg_config_manual.h.new src/include/pg_config_manual.h; \ 113 | gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \ 114 | \ 115 | # https://git.alpinelinux.org/aports/tree/community/postgresql15/APKBUILD?h=3.22-stable#n176 ("export LLVM_CONFIG") 116 | export LLVM_CONFIG="/usr/lib/llvm19/bin/llvm-config"; \ 117 | # https://git.alpinelinux.org/aports/tree/community/postgresql15/APKBUILD?h=3.22-stable#n180 ("older clang versions don't have a 'clang' exe anymore.") 118 | export CLANG=clang-19; \ 119 | \ 120 | # configure options taken from: 121 | # https://anonscm.debian.org/cgit/pkg-postgresql/postgresql.git/tree/debian/rules?h=9.5 122 | ./configure \ 123 | --enable-option-checking=fatal \ 124 | --build="$gnuArch" \ 125 | # "/usr/src/postgresql/src/backend/access/common/tupconvert.c:105: undefined reference to `libintl_gettext'" 126 | # --enable-nls \ 127 | --enable-integer-datetimes \ 128 | --enable-tap-tests \ 129 | # skip debugging info -- we want tiny size instead 130 | # --enable-debug \ 131 | --disable-rpath \ 132 | --with-uuid=e2fs \ 133 | --with-pgport=5432 \ 134 | --with-system-tzdata=/usr/share/zoneinfo \ 135 | --prefix=/usr/local \ 136 | --with-includes=/usr/local/include \ 137 | --with-libraries=/usr/local/lib \ 138 | --with-gssapi \ 139 | --with-ldap \ 140 | --with-tcl \ 141 | --with-perl \ 142 | --with-python \ 143 | # --with-pam \ 144 | --with-openssl \ 145 | --with-libxml \ 146 | --with-libxslt \ 147 | --with-icu \ 148 | --with-llvm \ 149 | --with-lz4 \ 150 | --with-zstd \ 151 | ; \ 152 | make -j "$(nproc)" world-bin; \ 153 | make install-world-bin; \ 154 | make -C contrib install; \ 155 | \ 156 | runDeps="$( \ 157 | scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \ 158 | | tr ',' '\n' \ 159 | | sort -u \ 160 | | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ 161 | # Remove plperl, plpython and pltcl dependencies by default to save image size 162 | # To use the pl extensions, those have to be installed in a derived image 163 | | grep -v -e perl -e python -e tcl \ 164 | )"; \ 165 | apk add --no-cache --virtual .postgresql-rundeps \ 166 | $runDeps \ 167 | bash \ 168 | tzdata \ 169 | zstd \ 170 | # https://wiki.alpinelinux.org/wiki/Release_Notes_for_Alpine_3.16.0#ICU_data_split 171 | icu-data-full \ 172 | # https://git.alpinelinux.org/aports/tree/community/nss_wrapper/APKBUILD?h=3.22-stable#n7 ("ppc64le: test case segfaults") 173 | $([ "$(apk --print-arch)" != 'ppc64le' ] && echo 'nss_wrapper') \ 174 | ; \ 175 | apk del --no-network .build-deps; \ 176 | cd /; \ 177 | rm -rf \ 178 | /usr/src/postgresql \ 179 | /usr/local/share/doc \ 180 | /usr/local/share/man \ 181 | ; \ 182 | \ 183 | postgres --version 184 | 185 | # make the sample config easier to munge (and "correct by default") 186 | RUN set -eux; \ 187 | cp -v /usr/local/share/postgresql/postgresql.conf.sample /usr/local/share/postgresql/postgresql.conf.sample.orig; \ 188 | sed -ri "s!^#?(listen_addresses)\s*=\s*\S+.*!\1 = '*'!" /usr/local/share/postgresql/postgresql.conf.sample; \ 189 | grep -F "listen_addresses = '*'" /usr/local/share/postgresql/postgresql.conf.sample 190 | 191 | RUN install --verbose --directory --owner postgres --group postgres --mode 3777 /var/run/postgresql 192 | 193 | ENV PGDATA /var/lib/postgresql/data 194 | # this 1777 will be replaced by 0700 at runtime (allows semi-arbitrary "--user" values) 195 | RUN install --verbose --directory --owner postgres --group postgres --mode 1777 "$PGDATA" 196 | VOLUME /var/lib/postgresql/data 197 | 198 | COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ 199 | RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh 200 | ENTRYPOINT ["docker-entrypoint.sh"] 201 | 202 | # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL 203 | # calls "Fast Shutdown mode" wherein new connections are disallowed and any 204 | # in-progress transactions are aborted, allowing PostgreSQL to stop cleanly and 205 | # flush tables to disk. 206 | # 207 | # See https://www.postgresql.org/docs/current/server-shutdown.html for more details 208 | # about available PostgreSQL server shutdown signals. 209 | # 210 | # See also https://www.postgresql.org/docs/current/server-start.html for further 211 | # justification of this as the default value, namely that the example (and 212 | # shipped) systemd service files use the "Fast Shutdown mode" for service 213 | # termination. 214 | # 215 | STOPSIGNAL SIGINT 216 | # 217 | # An additional setting that is recommended for all users regardless of this 218 | # value is the runtime "--stop-timeout" (or your orchestrator/runtime's 219 | # equivalent) for controlling how long to wait between sending the defined 220 | # STOPSIGNAL and sending SIGKILL. 221 | # 222 | # The default in most runtimes (such as Docker) is 10 seconds, and the 223 | # documentation at https://www.postgresql.org/docs/current/server-start.html notes 224 | # that even 90 seconds may not be long enough in many instances. 225 | 226 | EXPOSE 5432 227 | CMD ["postgres"] 228 | -------------------------------------------------------------------------------- /17/alpine3.22/docker-ensure-initdb.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | # 5 | # This script is intended for three main use cases: 6 | # 7 | # 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior 8 | # 9 | # 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution 10 | # (no-op if database is already initialized) 11 | # 12 | # 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use 13 | # (error if database is already initialized) 14 | # 15 | 16 | source /usr/local/bin/docker-entrypoint.sh 17 | 18 | # arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) 19 | if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then 20 | set -- postgres "$@" 21 | fi 22 | 23 | # see also "_main" in "docker-entrypoint.sh" 24 | 25 | docker_setup_env 26 | # setup data directories and permissions (when run as root) 27 | docker_create_db_directories 28 | if [ "$(id -u)" = '0' ]; then 29 | # then restart script as postgres user 30 | exec gosu postgres "$BASH_SOURCE" "$@" 31 | fi 32 | 33 | # only run initialization on an empty data directory 34 | if [ -z "$DATABASE_ALREADY_EXISTS" ]; then 35 | docker_verify_minimum_env 36 | 37 | # check dir permissions to reduce likelihood of half-initialized database 38 | ls /docker-entrypoint-initdb.d/ > /dev/null 39 | 40 | docker_init_database_dir 41 | pg_setup_hba_conf "$@" 42 | 43 | # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless 44 | # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS 45 | export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" 46 | docker_temp_server_start "$@" 47 | 48 | docker_setup_db 49 | docker_process_init_files /docker-entrypoint-initdb.d/* 50 | 51 | docker_temp_server_stop 52 | unset PGPASSWORD 53 | else 54 | self="$(basename "$0")" 55 | case "$self" in 56 | docker-ensure-initdb.sh) 57 | echo >&2 "$self: note: database already initialized in '$PGDATA'!" 58 | exit 0 59 | ;; 60 | 61 | docker-enforce-initdb.sh) 62 | echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" 63 | exit 1 64 | ;; 65 | 66 | *) 67 | echo >&2 "$self: error: unknown file name: $self" 68 | exit 99 69 | ;; 70 | esac 71 | fi 72 | -------------------------------------------------------------------------------- /17/bookworm/docker-ensure-initdb.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | # 5 | # This script is intended for three main use cases: 6 | # 7 | # 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior 8 | # 9 | # 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution 10 | # (no-op if database is already initialized) 11 | # 12 | # 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use 13 | # (error if database is already initialized) 14 | # 15 | 16 | source /usr/local/bin/docker-entrypoint.sh 17 | 18 | # arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) 19 | if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then 20 | set -- postgres "$@" 21 | fi 22 | 23 | # see also "_main" in "docker-entrypoint.sh" 24 | 25 | docker_setup_env 26 | # setup data directories and permissions (when run as root) 27 | docker_create_db_directories 28 | if [ "$(id -u)" = '0' ]; then 29 | # then restart script as postgres user 30 | exec gosu postgres "$BASH_SOURCE" "$@" 31 | fi 32 | 33 | # only run initialization on an empty data directory 34 | if [ -z "$DATABASE_ALREADY_EXISTS" ]; then 35 | docker_verify_minimum_env 36 | 37 | # check dir permissions to reduce likelihood of half-initialized database 38 | ls /docker-entrypoint-initdb.d/ > /dev/null 39 | 40 | docker_init_database_dir 41 | pg_setup_hba_conf "$@" 42 | 43 | # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless 44 | # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS 45 | export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" 46 | docker_temp_server_start "$@" 47 | 48 | docker_setup_db 49 | docker_process_init_files /docker-entrypoint-initdb.d/* 50 | 51 | docker_temp_server_stop 52 | unset PGPASSWORD 53 | else 54 | self="$(basename "$0")" 55 | case "$self" in 56 | docker-ensure-initdb.sh) 57 | echo >&2 "$self: note: database already initialized in '$PGDATA'!" 58 | exit 0 59 | ;; 60 | 61 | docker-enforce-initdb.sh) 62 | echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" 63 | exit 1 64 | ;; 65 | 66 | *) 67 | echo >&2 "$self: error: unknown file name: $self" 68 | exit 99 69 | ;; 70 | esac 71 | fi 72 | -------------------------------------------------------------------------------- /17/bullseye/docker-ensure-initdb.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | # 5 | # This script is intended for three main use cases: 6 | # 7 | # 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior 8 | # 9 | # 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution 10 | # (no-op if database is already initialized) 11 | # 12 | # 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use 13 | # (error if database is already initialized) 14 | # 15 | 16 | source /usr/local/bin/docker-entrypoint.sh 17 | 18 | # arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) 19 | if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then 20 | set -- postgres "$@" 21 | fi 22 | 23 | # see also "_main" in "docker-entrypoint.sh" 24 | 25 | docker_setup_env 26 | # setup data directories and permissions (when run as root) 27 | docker_create_db_directories 28 | if [ "$(id -u)" = '0' ]; then 29 | # then restart script as postgres user 30 | exec gosu postgres "$BASH_SOURCE" "$@" 31 | fi 32 | 33 | # only run initialization on an empty data directory 34 | if [ -z "$DATABASE_ALREADY_EXISTS" ]; then 35 | docker_verify_minimum_env 36 | 37 | # check dir permissions to reduce likelihood of half-initialized database 38 | ls /docker-entrypoint-initdb.d/ > /dev/null 39 | 40 | docker_init_database_dir 41 | pg_setup_hba_conf "$@" 42 | 43 | # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless 44 | # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS 45 | export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" 46 | docker_temp_server_start "$@" 47 | 48 | docker_setup_db 49 | docker_process_init_files /docker-entrypoint-initdb.d/* 50 | 51 | docker_temp_server_stop 52 | unset PGPASSWORD 53 | else 54 | self="$(basename "$0")" 55 | case "$self" in 56 | docker-ensure-initdb.sh) 57 | echo >&2 "$self: note: database already initialized in '$PGDATA'!" 58 | exit 0 59 | ;; 60 | 61 | docker-enforce-initdb.sh) 62 | echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" 63 | exit 1 64 | ;; 65 | 66 | *) 67 | echo >&2 "$self: error: unknown file name: $self" 68 | exit 99 69 | ;; 70 | esac 71 | fi 72 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Docker PostgreSQL Authors 2 | 3 | Tianon Gravi 4 | Joseph Ferguson 5 | 6 | And other contributors not specifically named here. 7 | -------------------------------------------------------------------------------- /Dockerfile-alpine.template: -------------------------------------------------------------------------------- 1 | {{ 2 | def alpine_version: 3 | env.variant | ltrimstr("alpine") 4 | -}} 5 | FROM alpine:{{ alpine_version }} 6 | 7 | # 70 is the standard uid/gid for "postgres" in Alpine 8 | # https://git.alpinelinux.org/aports/tree/main/postgresql-common/postgresql-common.pre-install?h=3.22-stable 9 | RUN set -eux; \ 10 | addgroup -g 70 -S postgres; \ 11 | adduser -u 70 -S -D -G postgres -H -h /var/lib/postgresql -s /bin/sh postgres; \ 12 | # also create the postgres user's home directory with appropriate permissions 13 | # see https://github.com/docker-library/postgres/issues/274 14 | install --verbose --directory --owner postgres --group postgres --mode 1777 /var/lib/postgresql 15 | 16 | # grab gosu for easy step-down from root 17 | # https://github.com/tianon/gosu/releases 18 | ENV GOSU_VERSION 1.17 19 | RUN set -eux; \ 20 | \ 21 | apk add --no-cache --virtual .gosu-deps \ 22 | ca-certificates \ 23 | dpkg \ 24 | gnupg \ 25 | ; \ 26 | \ 27 | dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')"; \ 28 | wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch"; \ 29 | wget -O /usr/local/bin/gosu.asc "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch.asc"; \ 30 | \ 31 | # verify the signature 32 | export GNUPGHOME="$(mktemp -d)"; \ 33 | gpg --batch --keyserver hkps://keys.openpgp.org --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4; \ 34 | gpg --batch --verify /usr/local/bin/gosu.asc /usr/local/bin/gosu; \ 35 | gpgconf --kill all; \ 36 | rm -rf "$GNUPGHOME" /usr/local/bin/gosu.asc; \ 37 | \ 38 | # clean up fetch dependencies 39 | apk del --no-network .gosu-deps; \ 40 | \ 41 | chmod +x /usr/local/bin/gosu; \ 42 | # verify that the binary works 43 | gosu --version; \ 44 | gosu nobody true 45 | {{ if env.version | IN("13", "14", "15", "16") then ( -}} 46 | RUN set -eux; ln -svf gosu /usr/local/bin/su-exec; su-exec nobody true # backwards compatibility (removed in PostgreSQL 17+) 47 | {{ ) else "" end -}} 48 | 49 | # make the "en_US.UTF-8" locale so postgres will be utf-8 enabled by default 50 | # alpine doesn't require explicit locale-file generation 51 | ENV LANG en_US.utf8 52 | 53 | RUN mkdir /docker-entrypoint-initdb.d 54 | 55 | ENV PG_MAJOR {{ env.version }} 56 | ENV PG_VERSION {{ .version }} 57 | ENV PG_SHA256 {{ .sha256 }} 58 | 59 | {{ 60 | def llvmver: 61 | "19" 62 | -}} 63 | ENV DOCKER_PG_LLVM_DEPS \ 64 | llvm{{ llvmver }}-dev \ 65 | clang{{ llvmver }} 66 | 67 | RUN set -eux; \ 68 | \ 69 | wget -O postgresql.tar.bz2 "https://ftp.postgresql.org/pub/source/v$PG_VERSION/postgresql-$PG_VERSION.tar.bz2"; \ 70 | echo "$PG_SHA256 *postgresql.tar.bz2" | sha256sum -c -; \ 71 | mkdir -p /usr/src/postgresql; \ 72 | tar \ 73 | --extract \ 74 | --file postgresql.tar.bz2 \ 75 | --directory /usr/src/postgresql \ 76 | --strip-components 1 \ 77 | ; \ 78 | rm postgresql.tar.bz2; \ 79 | \ 80 | apk add --no-cache --virtual .build-deps \ 81 | $DOCKER_PG_LLVM_DEPS \ 82 | bison \ 83 | coreutils \ 84 | dpkg-dev dpkg \ 85 | flex \ 86 | g++ \ 87 | gcc \ 88 | krb5-dev \ 89 | libc-dev \ 90 | libedit-dev \ 91 | libxml2-dev \ 92 | libxslt-dev \ 93 | linux-headers \ 94 | make \ 95 | openldap-dev \ 96 | openssl-dev \ 97 | perl-dev \ 98 | perl-ipc-run \ 99 | perl-utils \ 100 | python3-dev \ 101 | tcl-dev \ 102 | util-linux-dev \ 103 | zlib-dev \ 104 | # https://www.postgresql.org/docs/10/static/release-10.html#id-1.11.6.9.5.13 105 | icu-dev \ 106 | {{ if .major >= 14 then ( -}} 107 | # https://www.postgresql.org/docs/14/release-14.html#id-1.11.6.5.5.3.7 108 | lz4-dev \ 109 | {{ ) else "" end -}} 110 | {{ if .major >= 15 then ( -}} 111 | # https://www.postgresql.org/docs/15/release-15.html "--with-zstd to enable Zstandard builds" 112 | zstd-dev \ 113 | {{ ) else "" end -}} 114 | ; \ 115 | \ 116 | cd /usr/src/postgresql; \ 117 | # update "DEFAULT_PGSOCKET_DIR" to "/var/run/postgresql" (matching Debian) 118 | # see https://anonscm.debian.org/git/pkg-postgresql/postgresql.git/tree/debian/patches/51-default-sockets-in-var.patch?id=8b539fcb3e093a521c095e70bdfa76887217b89f 119 | awk '$1 == "#define" && $2 == "DEFAULT_PGSOCKET_DIR" && $3 == "\"/tmp\"" { $3 = "\"/var/run/postgresql\""; print; next } { print }' src/include/pg_config_manual.h > src/include/pg_config_manual.h.new; \ 120 | grep '/var/run/postgresql' src/include/pg_config_manual.h.new; \ 121 | mv src/include/pg_config_manual.h.new src/include/pg_config_manual.h; \ 122 | gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; \ 123 | \ 124 | # https://git.alpinelinux.org/aports/tree/community/postgresql15/APKBUILD?h=3.22-stable#n176 ("export LLVM_CONFIG") 125 | export LLVM_CONFIG="/usr/lib/llvm{{ llvmver }}/bin/llvm-config"; \ 126 | # https://git.alpinelinux.org/aports/tree/community/postgresql15/APKBUILD?h=3.22-stable#n180 ("older clang versions don't have a 'clang' exe anymore.") 127 | export CLANG=clang-{{ llvmver }}; \ 128 | \ 129 | # configure options taken from: 130 | # https://anonscm.debian.org/cgit/pkg-postgresql/postgresql.git/tree/debian/rules?h=9.5 131 | ./configure \ 132 | --enable-option-checking=fatal \ 133 | --build="$gnuArch" \ 134 | # "/usr/src/postgresql/src/backend/access/common/tupconvert.c:105: undefined reference to `libintl_gettext'" 135 | # --enable-nls \ 136 | --enable-integer-datetimes \ 137 | {{ if .major <= 16 then ( -}} 138 | {{ # in 17: this option is reversed. you need to disable it -}} 139 | --enable-thread-safety \ 140 | {{ ) else "" end -}} 141 | --enable-tap-tests \ 142 | # skip debugging info -- we want tiny size instead 143 | # --enable-debug \ 144 | --disable-rpath \ 145 | --with-uuid=e2fs \ 146 | {{ # in 16: "configure: error: unrecognized options: --with-gnu-ld" -}} 147 | {{ # https://github.com/postgres/postgres/commit/9db49fc5bfdc0126be03f4b8986013e59d93b91d -}} 148 | {{ if .major <= 15 then ( -}} 149 | --with-gnu-ld \ 150 | {{ ) else "" end -}} 151 | --with-pgport=5432 \ 152 | --with-system-tzdata=/usr/share/zoneinfo \ 153 | --prefix=/usr/local \ 154 | --with-includes=/usr/local/include \ 155 | --with-libraries=/usr/local/lib \ 156 | --with-gssapi \ 157 | --with-ldap \ 158 | --with-tcl \ 159 | --with-perl \ 160 | --with-python \ 161 | # --with-pam \ 162 | --with-openssl \ 163 | --with-libxml \ 164 | --with-libxslt \ 165 | --with-icu \ 166 | --with-llvm \ 167 | {{ if .major >= 14 then ( -}} 168 | --with-lz4 \ 169 | {{ ) else "" end -}} 170 | {{ if .major >= 15 then ( -}} 171 | --with-zstd \ 172 | {{ ) else "" end -}} 173 | ; \ 174 | make -j "$(nproc)" world-bin; \ 175 | make install-world-bin; \ 176 | make -C contrib install; \ 177 | \ 178 | runDeps="$( \ 179 | scanelf --needed --nobanner --format '%n#p' --recursive /usr/local \ 180 | | tr ',' '\n' \ 181 | | sort -u \ 182 | | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ 183 | # Remove plperl, plpython and pltcl dependencies by default to save image size 184 | # To use the pl extensions, those have to be installed in a derived image 185 | | grep -v -e perl -e python -e tcl \ 186 | )"; \ 187 | apk add --no-cache --virtual .postgresql-rundeps \ 188 | $runDeps \ 189 | bash \ 190 | tzdata \ 191 | zstd \ 192 | # https://wiki.alpinelinux.org/wiki/Release_Notes_for_Alpine_3.16.0#ICU_data_split 193 | icu-data-full \ 194 | # https://git.alpinelinux.org/aports/tree/community/nss_wrapper/APKBUILD?h=3.22-stable#n7 ("ppc64le: test case segfaults") 195 | $([ "$(apk --print-arch)" != 'ppc64le' ] && echo 'nss_wrapper') \ 196 | ; \ 197 | apk del --no-network .build-deps; \ 198 | cd /; \ 199 | rm -rf \ 200 | /usr/src/postgresql \ 201 | /usr/local/share/doc \ 202 | /usr/local/share/man \ 203 | ; \ 204 | \ 205 | postgres --version 206 | 207 | # make the sample config easier to munge (and "correct by default") 208 | RUN set -eux; \ 209 | cp -v /usr/local/share/postgresql/postgresql.conf.sample /usr/local/share/postgresql/postgresql.conf.sample.orig; \ 210 | sed -ri "s!^#?(listen_addresses)\s*=\s*\S+.*!\1 = '*'!" /usr/local/share/postgresql/postgresql.conf.sample; \ 211 | grep -F "listen_addresses = '*'" /usr/local/share/postgresql/postgresql.conf.sample 212 | 213 | RUN install --verbose --directory --owner postgres --group postgres --mode 3777 /var/run/postgresql 214 | 215 | ENV PGDATA /var/lib/postgresql/data 216 | # this 1777 will be replaced by 0700 at runtime (allows semi-arbitrary "--user" values) 217 | RUN install --verbose --directory --owner postgres --group postgres --mode 1777 "$PGDATA" 218 | VOLUME /var/lib/postgresql/data 219 | 220 | COPY docker-entrypoint.sh docker-ensure-initdb.sh /usr/local/bin/ 221 | RUN ln -sT docker-ensure-initdb.sh /usr/local/bin/docker-enforce-initdb.sh 222 | ENTRYPOINT ["docker-entrypoint.sh"] 223 | 224 | # We set the default STOPSIGNAL to SIGINT, which corresponds to what PostgreSQL 225 | # calls "Fast Shutdown mode" wherein new connections are disallowed and any 226 | # in-progress transactions are aborted, allowing PostgreSQL to stop cleanly and 227 | # flush tables to disk. 228 | # 229 | # See https://www.postgresql.org/docs/current/server-shutdown.html for more details 230 | # about available PostgreSQL server shutdown signals. 231 | # 232 | # See also https://www.postgresql.org/docs/current/server-start.html for further 233 | # justification of this as the default value, namely that the example (and 234 | # shipped) systemd service files use the "Fast Shutdown mode" for service 235 | # termination. 236 | # 237 | STOPSIGNAL SIGINT 238 | # 239 | # An additional setting that is recommended for all users regardless of this 240 | # value is the runtime "--stop-timeout" (or your orchestrator/runtime's 241 | # equivalent) for controlling how long to wait between sending the defined 242 | # STOPSIGNAL and sending SIGKILL. 243 | # 244 | # The default in most runtimes (such as Docker) is 10 seconds, and the 245 | # documentation at https://www.postgresql.org/docs/current/server-start.html notes 246 | # that even 90 seconds may not be long enough in many instances. 247 | 248 | EXPOSE 5432 249 | CMD ["postgres"] 250 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, Docker PostgreSQL Authors (See AUTHORS) 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # https://github.com/docker-library/postgres 2 | 3 | ## Maintained by: [the PostgreSQL Docker Community](https://github.com/docker-library/postgres) 4 | 5 | This is the Git repo of the [Docker "Official Image"](https://github.com/docker-library/official-images#what-are-official-images) for [`postgres`](https://hub.docker.com/_/postgres/) (not to be confused with any official `postgres` image provided by `postgres` upstream). See [the Docker Hub page](https://hub.docker.com/_/postgres/) for the full readme on how to use this Docker image and for information regarding contributing and issues. 6 | 7 | The [full image description on Docker Hub](https://hub.docker.com/_/postgres/) is generated/maintained over in [the docker-library/docs repository](https://github.com/docker-library/docs), specifically in [the `postgres` directory](https://github.com/docker-library/docs/tree/master/postgres). 8 | 9 | ## See a change merged here that doesn't show up on Docker Hub yet? 10 | 11 | For more information about the full official images change lifecycle, see [the "An image's source changed in Git, now what?" FAQ entry](https://github.com/docker-library/faq#an-images-source-changed-in-git-now-what). 12 | 13 | For outstanding `postgres` image PRs, check [PRs with the "library/postgres" label on the official-images repository](https://github.com/docker-library/official-images/labels/library%2Fpostgres). For the current "source of truth" for [`postgres`](https://hub.docker.com/_/postgres/), see [the `library/postgres` file in the official-images repository](https://github.com/docker-library/official-images/blob/master/library/postgres). 14 | 15 | 16 | -------------------------------------------------------------------------------- /apply-templates.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | [ -f versions.json ] # run "versions.sh" first 5 | 6 | cd "$(dirname "$(readlink -f "$BASH_SOURCE")")" 7 | 8 | jqt='.jq-template.awk' 9 | if [ -n "${BASHBREW_SCRIPTS:-}" ]; then 10 | jqt="$BASHBREW_SCRIPTS/jq-template.awk" 11 | elif [ "$BASH_SOURCE" -nt "$jqt" ]; then 12 | # https://github.com/docker-library/bashbrew/blob/master/scripts/jq-template.awk 13 | wget -qO "$jqt" 'https://github.com/docker-library/bashbrew/raw/9f6a35772ac863a0241f147c820354e4008edf38/scripts/jq-template.awk' 14 | fi 15 | 16 | if [ "$#" -eq 0 ]; then 17 | versions="$(jq -r 'keys | map(@sh) | join(" ")' versions.json)" 18 | eval "set -- $versions" 19 | fi 20 | 21 | generated_warning() { 22 | cat <<-EOH 23 | # 24 | # NOTE: THIS DOCKERFILE IS GENERATED VIA "apply-templates.sh" 25 | # 26 | # PLEASE DO NOT EDIT IT DIRECTLY. 27 | # 28 | 29 | EOH 30 | } 31 | 32 | for version; do 33 | export version 34 | 35 | major="$(jq -r '.[env.version].major' versions.json)" 36 | 37 | variants="$(jq -r '.[env.version].variants | map(@sh) | join(" ")' versions.json)" 38 | eval "variants=( $variants )" 39 | 40 | rm -rf "$version" 41 | 42 | for variant in "${variants[@]}"; do 43 | export variant 44 | 45 | dir="$version/$variant" 46 | mkdir -p "$dir" 47 | 48 | echo "processing $dir ..." 49 | 50 | case "$variant" in 51 | alpine*) 52 | template='Dockerfile-alpine.template' 53 | ;; 54 | *) 55 | template='Dockerfile-debian.template' 56 | ;; 57 | esac 58 | 59 | { 60 | generated_warning 61 | gawk -f "$jqt" "$template" 62 | } > "$dir/Dockerfile" 63 | 64 | cp -a docker-entrypoint.sh docker-ensure-initdb.sh "$dir/" 65 | done 66 | done 67 | -------------------------------------------------------------------------------- /docker-ensure-initdb.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | # 5 | # This script is intended for three main use cases: 6 | # 7 | # 1. (most importantly) as an example of how to use "docker-entrypoint.sh" to extend/reuse the initialization behavior 8 | # 9 | # 2. ("docker-ensure-initdb.sh") as a Kubernetes "init container" to ensure the provided database directory is initialized; see also "startup probes" for an alternative solution 10 | # (no-op if database is already initialized) 11 | # 12 | # 3. ("docker-enforce-initdb.sh") as part of CI to ensure the database is fully initialized before use 13 | # (error if database is already initialized) 14 | # 15 | 16 | source /usr/local/bin/docker-entrypoint.sh 17 | 18 | # arguments to this script are assumed to be arguments to the "postgres" server (same as "docker-entrypoint.sh"), and most "docker-entrypoint.sh" functions assume "postgres" is the first argument (see "_main" over there) 19 | if [ "$#" -eq 0 ] || [ "$1" != 'postgres' ]; then 20 | set -- postgres "$@" 21 | fi 22 | 23 | # see also "_main" in "docker-entrypoint.sh" 24 | 25 | docker_setup_env 26 | # setup data directories and permissions (when run as root) 27 | docker_create_db_directories 28 | if [ "$(id -u)" = '0' ]; then 29 | # then restart script as postgres user 30 | exec gosu postgres "$BASH_SOURCE" "$@" 31 | fi 32 | 33 | # only run initialization on an empty data directory 34 | if [ -z "$DATABASE_ALREADY_EXISTS" ]; then 35 | docker_verify_minimum_env 36 | 37 | # check dir permissions to reduce likelihood of half-initialized database 38 | ls /docker-entrypoint-initdb.d/ > /dev/null 39 | 40 | docker_init_database_dir 41 | pg_setup_hba_conf "$@" 42 | 43 | # PGPASSWORD is required for psql when authentication is required for 'local' connections via pg_hba.conf and is otherwise harmless 44 | # e.g. when '--auth=md5' or '--auth-local=md5' is used in POSTGRES_INITDB_ARGS 45 | export PGPASSWORD="${PGPASSWORD:-$POSTGRES_PASSWORD}" 46 | docker_temp_server_start "$@" 47 | 48 | docker_setup_db 49 | docker_process_init_files /docker-entrypoint-initdb.d/* 50 | 51 | docker_temp_server_stop 52 | unset PGPASSWORD 53 | else 54 | self="$(basename "$0")" 55 | case "$self" in 56 | docker-ensure-initdb.sh) 57 | echo >&2 "$self: note: database already initialized in '$PGDATA'!" 58 | exit 0 59 | ;; 60 | 61 | docker-enforce-initdb.sh) 62 | echo >&2 "$self: error: (unexpected) database found in '$PGDATA'!" 63 | exit 1 64 | ;; 65 | 66 | *) 67 | echo >&2 "$self: error: unknown file name: $self" 68 | exit 99 69 | ;; 70 | esac 71 | fi 72 | -------------------------------------------------------------------------------- /generate-stackbrew-library.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | declare -A aliases=( 5 | [17]='latest' 6 | ) 7 | 8 | self="$(basename "$BASH_SOURCE")" 9 | cd "$(dirname "$(readlink -f "$BASH_SOURCE")")" 10 | 11 | if [ "$#" -eq 0 ]; then 12 | versions="$(jq -r 'keys | map(@sh) | join(" ")' versions.json)" 13 | eval "set -- $versions" 14 | fi 15 | 16 | # sort version numbers with highest first 17 | IFS=$'\n'; set -- $(sort -rV <<<"$*"); unset IFS 18 | 19 | # get the most recent commit which modified any of "$@" 20 | fileCommit() { 21 | git log -1 --format='format:%H' HEAD -- "$@" 22 | } 23 | 24 | # get the most recent commit which modified "$1/Dockerfile" or any file COPY'd from "$1/Dockerfile" 25 | dirCommit() { 26 | local dir="$1"; shift 27 | ( 28 | cd "$dir" 29 | files="$( 30 | git show HEAD:./Dockerfile | awk ' 31 | toupper($1) == "COPY" { 32 | for (i = 2; i < NF; i++) { 33 | if ($i ~ /^--from=/) { 34 | next 35 | } 36 | print $i 37 | } 38 | } 39 | ' 40 | )" 41 | fileCommit Dockerfile $files 42 | ) 43 | } 44 | 45 | getArches() { 46 | local repo="$1"; shift 47 | local officialImagesBase="${BASHBREW_LIBRARY:-https://github.com/docker-library/official-images/raw/HEAD/library}/" 48 | 49 | local parentRepoToArchesStr 50 | parentRepoToArchesStr="$( 51 | find -name 'Dockerfile' -exec awk -v officialImagesBase="$officialImagesBase" ' 52 | toupper($1) == "FROM" && $2 !~ /^('"$repo"'|scratch|.*\/.*)(:|$)/ { 53 | printf "%s%s\n", officialImagesBase, $2 54 | } 55 | ' '{}' + \ 56 | | sort -u \ 57 | | xargs -r bashbrew cat --format '["{{ .RepoName }}:{{ .TagName }}"]="{{ join " " .TagEntry.Architectures }}"' 58 | )" 59 | eval "declare -g -A parentRepoToArches=( $parentRepoToArchesStr )" 60 | } 61 | getArches 'postgres' 62 | 63 | cat <<-EOH 64 | # this file is generated via https://github.com/docker-library/postgres/blob/$(fileCommit "$self")/$self 65 | 66 | Maintainers: Tianon Gravi (@tianon), 67 | Joseph Ferguson (@yosifkit) 68 | GitRepo: https://github.com/docker-library/postgres.git 69 | EOH 70 | 71 | # prints "$2$1$3$1...$N" 72 | join() { 73 | local sep="$1"; shift 74 | local out; printf -v out "${sep//%/%%}%s" "$@" 75 | echo "${out#$sep}" 76 | } 77 | 78 | for version; do 79 | export version 80 | 81 | variants="$(jq -r '.[env.version].variants | map(@sh) | join(" ")' versions.json)" 82 | eval "variants=( $variants )" 83 | 84 | alpine="$(jq -r '.[env.version].alpine' versions.json)" 85 | debian="$(jq -r '.[env.version].debian' versions.json)" 86 | 87 | fullVersion="$(jq -r '.[env.version].version' versions.json)" 88 | 89 | # ex: 9.6.22, 13.3, or 14beta2 90 | versionAliases=( 91 | $fullVersion 92 | ) 93 | # skip unadorned "version" on prereleases: https://www.postgresql.org/developer/beta/ 94 | # ex: 9.6, 13, or 14 95 | case "$fullVersion" in 96 | *alpha* | *beta* | *rc*) ;; 97 | *) versionAliases+=( $version ) ;; 98 | esac 99 | # ex: 9 or latest 100 | versionAliases+=( 101 | ${aliases[$version]:-} 102 | ) 103 | 104 | for variant in "${variants[@]}"; do 105 | dir="$version/$variant" 106 | commit="$(dirCommit "$dir")" 107 | 108 | parent="$(awk 'toupper($1) == "FROM" { print $2 }' "$dir/Dockerfile")" 109 | arches="${parentRepoToArches[$parent]}" 110 | 111 | variantAliases=( "${versionAliases[@]/%/-$variant}" ) 112 | variantAliases=( "${variantAliases[@]//latest-/}" ) 113 | 114 | case "$variant" in 115 | "$debian") 116 | variantAliases=( 117 | "${versionAliases[@]}" 118 | "${variantAliases[@]}" 119 | ) 120 | ;; 121 | alpine"$alpine") 122 | variantAliases+=( "${versionAliases[@]/%/-alpine}" ) 123 | variantAliases=( "${variantAliases[@]//latest-/}" ) 124 | ;; 125 | esac 126 | 127 | echo 128 | cat <<-EOE 129 | Tags: $(join ', ' "${variantAliases[@]}") 130 | Architectures: $(join ', ' $arches) 131 | GitCommit: $commit 132 | Directory: $dir 133 | EOE 134 | done 135 | done 136 | -------------------------------------------------------------------------------- /update.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | cd "$(dirname "$(readlink -f "$BASH_SOURCE")")" 5 | 6 | ./versions.sh "$@" 7 | ./apply-templates.sh "$@" 8 | -------------------------------------------------------------------------------- /versions.json: -------------------------------------------------------------------------------- 1 | { 2 | "13": { 3 | "alpine": "3.22", 4 | "bookworm": { 5 | "arches": [ 6 | "amd64", 7 | "arm64", 8 | "ppc64el" 9 | ], 10 | "version": "13.21-1.pgdg120+1" 11 | }, 12 | "bullseye": { 13 | "arches": [ 14 | "amd64", 15 | "arm64", 16 | "ppc64el" 17 | ], 18 | "version": "13.21-1.pgdg110+1" 19 | }, 20 | "debian": "bookworm", 21 | "major": 13, 22 | "sha256": "dcda1294df45f033b0656cf7a8e4afbbc624c25e1b144aec79530f74d7ef4ab4", 23 | "variants": [ 24 | "bookworm", 25 | "bullseye", 26 | "alpine3.22", 27 | "alpine3.21" 28 | ], 29 | "version": "13.21" 30 | }, 31 | "14": { 32 | "alpine": "3.22", 33 | "bookworm": { 34 | "arches": [ 35 | "amd64", 36 | "arm64", 37 | "ppc64el" 38 | ], 39 | "version": "14.18-1.pgdg120+1" 40 | }, 41 | "bullseye": { 42 | "arches": [ 43 | "amd64", 44 | "arm64", 45 | "ppc64el" 46 | ], 47 | "version": "14.18-1.pgdg110+1" 48 | }, 49 | "debian": "bookworm", 50 | "major": 14, 51 | "sha256": "83ab29d6bfc3dc58b2ed3c664114fdfbeb6a0450c4b8d7fa69aee91e3ca14f8e", 52 | "variants": [ 53 | "bookworm", 54 | "bullseye", 55 | "alpine3.22", 56 | "alpine3.21" 57 | ], 58 | "version": "14.18" 59 | }, 60 | "15": { 61 | "alpine": "3.22", 62 | "bookworm": { 63 | "arches": [ 64 | "amd64", 65 | "arm64", 66 | "ppc64el" 67 | ], 68 | "version": "15.13-1.pgdg120+1" 69 | }, 70 | "bullseye": { 71 | "arches": [ 72 | "amd64", 73 | "arm64", 74 | "ppc64el" 75 | ], 76 | "version": "15.13-1.pgdg110+1" 77 | }, 78 | "debian": "bookworm", 79 | "major": 15, 80 | "sha256": "4f62e133d22ea08a0401b0840920e26698644d01a80c34341fb732dd0a90ca5d", 81 | "variants": [ 82 | "bookworm", 83 | "bullseye", 84 | "alpine3.22", 85 | "alpine3.21" 86 | ], 87 | "version": "15.13" 88 | }, 89 | "16": { 90 | "alpine": "3.22", 91 | "bookworm": { 92 | "arches": [ 93 | "amd64", 94 | "arm64", 95 | "ppc64el" 96 | ], 97 | "version": "16.9-1.pgdg120+1" 98 | }, 99 | "bullseye": { 100 | "arches": [ 101 | "amd64", 102 | "arm64", 103 | "ppc64el" 104 | ], 105 | "version": "16.9-1.pgdg110+1" 106 | }, 107 | "debian": "bookworm", 108 | "major": 16, 109 | "sha256": "07c00fb824df0a0c295f249f44691b86e3266753b380c96f633c3311e10bd005", 110 | "variants": [ 111 | "bookworm", 112 | "bullseye", 113 | "alpine3.22", 114 | "alpine3.21" 115 | ], 116 | "version": "16.9" 117 | }, 118 | "17": { 119 | "alpine": "3.22", 120 | "bookworm": { 121 | "arches": [ 122 | "amd64", 123 | "arm64", 124 | "ppc64el" 125 | ], 126 | "version": "17.5-1.pgdg120+1" 127 | }, 128 | "bullseye": { 129 | "arches": [ 130 | "amd64", 131 | "arm64", 132 | "ppc64el" 133 | ], 134 | "version": "17.5-1.pgdg110+1" 135 | }, 136 | "debian": "bookworm", 137 | "major": 17, 138 | "sha256": "fcb7ab38e23b264d1902cb25e6adafb4525a6ebcbd015434aeef9eda80f528d8", 139 | "variants": [ 140 | "bookworm", 141 | "bullseye", 142 | "alpine3.22", 143 | "alpine3.21" 144 | ], 145 | "version": "17.5" 146 | } 147 | } 148 | -------------------------------------------------------------------------------- /versions.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -Eeuo pipefail 3 | 4 | # we will support at most two entries in each of these lists, and both should be in descending order 5 | supportedDebianSuites=( 6 | bookworm 7 | bullseye 8 | ) 9 | supportedAlpineVersions=( 10 | 3.22 11 | 3.21 12 | ) 13 | defaultDebianSuite="${supportedDebianSuites[0]}" 14 | declare -A debianSuites=( 15 | ) 16 | defaultAlpineVersion="${supportedAlpineVersions[0]}" 17 | declare -A alpineVersions=( 18 | #[14]='3.16' 19 | ) 20 | 21 | cd "$(dirname "$(readlink -f "$BASH_SOURCE")")" 22 | 23 | versions=( "$@" ) 24 | if [ ${#versions[@]} -eq 0 ]; then 25 | versions=( */ ) 26 | json='{}' 27 | else 28 | json="$(< versions.json)" 29 | fi 30 | versions=( "${versions[@]%/}" ) 31 | 32 | packagesBase='http://apt.postgresql.org/pub/repos/apt/dists/' 33 | declare -A suitePackageList=() suiteVersionPackageList=() suiteArches=() 34 | _raw_package_list() { 35 | local suite="$1"; shift 36 | local component="$1"; shift 37 | local arch="$1"; shift 38 | 39 | curl -fsSL "$packagesBase/$suite-pgdg/$component/binary-$arch/Packages.bz2" | bunzip2 40 | } 41 | fetch_suite_package_list() { 42 | local -; set +x # make sure running with "set -x" doesn't spam the terminal with the raw package lists 43 | 44 | local suite="$1"; shift 45 | local version="$1"; shift 46 | local arch="$1"; shift 47 | 48 | # normal (GA) releases end up in the "main" component of upstream's repository 49 | if [ -z "${suitePackageList["$suite-$arch"]:+isset}" ]; then 50 | local suiteArchPackageList 51 | suiteArchPackageList="$(_raw_package_list "$suite" 'main' "$arch")" 52 | suitePackageList["$suite-$arch"]="$suiteArchPackageList" 53 | fi 54 | 55 | # ... but pre-release versions (betas, etc) end up in the "PG_MAJOR" component (so we need to check both) 56 | if [ -z "${suiteVersionPackageList["$suite-$version-$arch"]:+isset}" ]; then 57 | local versionPackageList 58 | versionPackageList="$(_raw_package_list "$suite" "$version" "$arch")" 59 | suiteVersionPackageList["$suite-$version-$arch"]="$versionPackageList" 60 | fi 61 | } 62 | awk_package_list() { 63 | local suite="$1"; shift 64 | local version="$1"; shift 65 | local arch="$1"; shift 66 | 67 | awk -F ': ' -v version="$version" "$@" <<<"${suitePackageList["$suite-$arch"]}"$'\n'"${suiteVersionPackageList["$suite-$version-$arch"]}" 68 | } 69 | fetch_suite_arches() { 70 | local suite="$1"; shift 71 | 72 | if [ -z "${suiteArches["$suite"]:+isset}" ]; then 73 | local suiteRelease 74 | suiteRelease="$(curl -fsSL "$packagesBase/$suite-pgdg/Release")" 75 | suiteArches["$suite"]="$(gawk <<<"$suiteRelease" -F ':[[:space:]]+' '$1 == "Architectures" { print $2; exit }')" 76 | fi 77 | } 78 | 79 | for version in "${versions[@]}"; do 80 | export version 81 | 82 | versionAlpineVersion="${alpineVersions[$version]:-$defaultAlpineVersion}" 83 | versionDebianSuite="${debianSuites[$version]:-$defaultDebianSuite}" 84 | export versionAlpineVersion versionDebianSuite 85 | 86 | doc="$(jq -nc '{ 87 | alpine: env.versionAlpineVersion, 88 | debian: env.versionDebianSuite, 89 | }')" 90 | 91 | fullVersion= 92 | for suite in "${supportedDebianSuites[@]}"; do 93 | fetch_suite_package_list "$suite" "$version" 'amd64' 94 | suiteVersions="$(awk_package_list "$suite" "$version" 'amd64' ' 95 | $1 == "Package" { pkg = $2 } 96 | $1 == "Version" && pkg == "postgresql-" version { print $2 } 97 | ' | sort -V)" 98 | suiteVersion="$(tail -1 <<<"$suiteVersions")" # "15~beta4-1.pgdg110+1" 99 | srcVersion="${suiteVersion%%-*}" # "15~beta4" 100 | tilde='~' 101 | srcVersion="${srcVersion//$tilde/}" # "15beta4" 102 | [ -n "$fullVersion" ] || fullVersion="$srcVersion" 103 | if [ "$fullVersion" != "$srcVersion" ]; then 104 | echo >&2 "warning: $version should be '$fullVersion' but $suite has '$srcVersion' ($suiteVersion)" 105 | continue 106 | fi 107 | 108 | versionArches='[]' 109 | fetch_suite_arches "$suite" 110 | for arch in ${suiteArches["$suite"]}; do 111 | fetch_suite_package_list "$suite" "$version" "$arch" 112 | archVersion="$(awk_package_list "$suite" "$version" "$arch" ' 113 | $1 == "Package" { pkg = $2 } 114 | $1 == "Version" && pkg == "postgresql-" version { print $2; exit } 115 | ')" 116 | if [ "$archVersion" = "$suiteVersion" ]; then 117 | versionArches="$(jq <<<"$versionArches" -c --arg arch "$arch" '. += [$arch]')" 118 | fi 119 | done 120 | 121 | export suite suiteVersion 122 | doc="$(jq <<<"$doc" -c --argjson arches "$versionArches" ' 123 | .[env.suite] = { 124 | version: env.suiteVersion, 125 | arches: $arches, 126 | } 127 | | .variants += [ env.suite ] 128 | ')" 129 | done 130 | 131 | for alpineVersion in "${supportedAlpineVersions[@]}"; do 132 | doc="$(jq <<<"$doc" -c --arg v "$alpineVersion" ' 133 | .variants += [ "alpine" + $v ] 134 | ')" 135 | done 136 | 137 | sha256="$( 138 | curl -fsSL "https://ftp.postgresql.org/pub/source/v${fullVersion}/postgresql-${fullVersion}.tar.bz2.sha256" \ 139 | | cut -d' ' -f1 140 | )" 141 | 142 | echo "$version: $fullVersion" 143 | 144 | export fullVersion sha256 major="${version%%.*}" 145 | json="$(jq <<<"$json" -c --argjson doc "$doc" ' 146 | .[env.version] = ($doc + { 147 | version: env.fullVersion, 148 | sha256: env.sha256, 149 | major: (env.major | tonumber), 150 | }) 151 | ')" 152 | done 153 | 154 | jq <<<"$json" -S . > versions.json 155 | --------------------------------------------------------------------------------