From 193421918b035d1a7111a45b2587804990c12817 Mon Sep 17 00:00:00 2001 From: "David E. Wheeler" Date: Tue, 11 Mar 2025 15:22:31 -0400 Subject: [PATCH] Move and configure lib directories (#98) Instead of OS-specific and Postgres version-specific `lib` directories, just have `mod` for Postgres extension module files and `lib` for shared libraries they depend on. For example, the `pgsql_http` extension's `http.so` file would be installed in `mod` and its dependency, `libcurl`, in `lib`. Both remain part of the `postgres` binary's runpath: ```console /usr/lib/postgresql/bin/postgres: RUNPATH=/usr/lib/postgresql/lib:/var/lib/postgresql/tembo/mod:/var/lib/postgresql/tembo/lib ``` While at it, remove LLVM, Python, Tcl, and Perl from the base image, eliminating around 180MB from the image size. LLVM is not needed on the image, and the dynamic language libraries only needed if their accompanying extensions are installed; we'll want to install them when their extensions are installed. Update `docker-entrypoint.sh` to add `/var/lib/postgresql/tembo/mod` to the `dynamic_library_path`, so that Postgres can find extension modules there. Control files will need `$libdir/` stripped from `module_pathname` for this to work, a change likely to be included in Postgres 18 but we'll have to do when installing extensions there. Other changes: * Fix workflow push on main an move a couple of `Dockerfile` items around. * Update the image URLs and directory descriptions the READMEs. --- .github/workflows/bake.yaml | 2 +- CONTAINER_README.md | 9 ++------- Dockerfile | 14 ++++++-------- README.md | 15 ++++++++------- docker-bake.hcl | 4 ++-- docker-entrypoint.sh | 21 +++++++++++++++------ 6 files changed, 34 insertions(+), 31 deletions(-) diff --git a/.github/workflows/bake.yaml b/.github/workflows/bake.yaml index 548da2f..3eb0b5a 100644 --- a/.github/workflows/bake.yaml +++ b/.github/workflows/bake.yaml @@ -61,7 +61,7 @@ jobs: with: pull: true # Push only on main. - set: ${{ github.ref_name == 'main' && '' || '*.output=type=cacheonly' }} + set: "*.output=type=${{ github.ref_name == 'main' && 'image,push-by-digest=true,push=true' || 'cacheonly' }}" - name: Save Metadata run: echo '${{ steps.build.outputs.metadata }}' > build-${{ matrix.arch[1] }}-${{ matrix.os[1] }}-${{ matrix.pg }}.json - name: Upload Metadata diff --git a/CONTAINER_README.md b/CONTAINER_README.md index c159860..582e55f 100644 --- a/CONTAINER_README.md +++ b/CONTAINER_README.md @@ -12,17 +12,12 @@ their purposes: * `tembo`: The directory that [Tembo Cloud] mounts as the persistent volume for the database and extensions. * `tembo/pgdata`: The data directory initialized by [Tembo Cloud]. +* `tembo/lib`: A directory for shared library files required by extensions. +* `tembo/mod`: A directory for extension module library files. * `tembo/share`: The directory for architecture-independent support files used by Postgres. This is the directory used by `pg_config --sharedir` to install non-binary extension files. Its files are copied from `/tmp/pg_sharedir` when the Tembo operator initializes the volume. -* `tembo/${PG_MAJOR}/lib`: A directory for extension shared library files - compiled for a specific major version of Postgres. -* `tembo/${OS_NAME}/lib`: A directory for OS shared library files. -* `tembo/${OS_NAME}/etc`: The home of the library loading cache, updated - by `ldconfig` when new files are installed into - `tembo/${OS_NAME}/lib`. The canonical cache file, `/etc/ld.so.cache`, - is a symlink into this directory. Other useful locations around the system: diff --git a/Dockerfile b/Dockerfile index 78a8b75..385232c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,8 +11,8 @@ ARG CNPG_VOLUME=${PG_HOME}/data # System LLD dir. ARG TEMBO_VOLUME=${PG_HOME}/tembo ARG TEMBO_SHARE_DIR=${TEMBO_VOLUME}/share -ARG TEMBO_PG_LIB_DIR=${TEMBO_VOLUME}/${PG_MAJOR}/lib -ARG TEMBO_LD_LIB_DIR=${TEMBO_VOLUME}/${OS_NAME}/lib +ARG TEMBO_PG_LIB_DIR=${TEMBO_VOLUME}/mod +ARG TEMBO_LD_LIB_DIR=${TEMBO_VOLUME}/lib # Set rpath to search the Postgres lib directory, then the Tembo Postgres lib # directory, where Trunk-installed extension libraries will live, and the @@ -126,7 +126,8 @@ RUN set -ex; \ useradd -r -g postgres --uid=26 --home-dir=${PG_HOME} --shell=/bin/bash postgres && \ chown -R postgres:postgres ${PG_HOME}; -# Add the entrypoint script +# Add the README and entrypoint script. +COPY CONTAINER_README.md "${PG_HOME}/README.md" COPY docker-entrypoint.sh /usr/local/bin/ ############################################################################## @@ -163,7 +164,6 @@ RUN apt-get update && apt-get upgrade -y && apt-get install --no-install-recomme libxml2 \ libxslt1.1 \ libreadline8 \ - libtcl8.6 \ xz-utils \ libgss3 \ libkrb5-3 \ @@ -182,17 +182,15 @@ RUN set -xe; \ # initialization without a temp copy: https://stackoverflow.com/a/72269316/79202) cp -lr "$(pg_config --sharedir)" /tmp/pg_sharedir; -# Add the README. +# Add the README and entrypoint script. COPY CONTAINER_README.md "${PG_HOME}/README.md" +COPY docker-entrypoint.sh /usr/local/bin/ # Create the Postgres user and set its uid to what CNPG expects. RUN groupadd -r postgres --gid=999 && \ useradd -r -g postgres --uid=26 --home-dir=${PG_HOME} --shell=/bin/bash postgres && \ chown -R postgres:postgres ${PG_HOME}; -# Add the entrypoint script -COPY docker-entrypoint.sh /usr/local/bin/ - ############################################################################## # Build the postgres image as a single layer. FROM scratch AS postgres diff --git a/README.md b/README.md index 8cb799d..e926679 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Ubuntu Noble (24.04) and Jimmy (22.04) for the ARM64 and AMD64 processors. inside the container: ```sh - docker run --name tembo-postgres -d localhost:5001/postgres:17 + docker run --name tembo-postgres -d quay.io/tembo/postgres docker exec -it tembo-postgres psql ``` @@ -97,7 +97,7 @@ To run the image locally with the Tembo Operator, you'll need: 5. Edit `yaml/sample-standard.yaml` and set `image` to the image name: ```yaml - image: localhost:5001/postgres:17 + image: localhost:5001/postgres:latest ``` 6. Load the image into the `kind` Kubernetes registry and create the cluster: @@ -158,11 +158,12 @@ And an image built on the latest Postgres includes the tag: * `/var/lib/postgresql/tembo`: The directory where [Tembo Cloud] mounts a persistent volume and stores persistent data: - * Tembo initializes and runs the cluster from the `pgdata` subdirectory. - * Given a Postgres major version, e.g., `17`, the Tembo stores extension - shared libraries in `17/lib` and extension data files in `17/share`. - * Given an Ubuntu code name, such as `noble`, Tembo stores shared system - libraries required by extensions in `noble/lib`. + * `pgdata`: Tembo initializes and runs the cluster from this + subdirectory. + * `mod`: Tembo stores extension module libraries this subdirectory. + * `share`: Tembo stores and extension data files in this subdirectory. + * `lib`: Tembo stores shared libraries required by extensions in this + subdirectory. * `/usr/lib/postgresql`: The home of the PostgreSQL binaries, libraries, and header & locale files. Immutable in [CloudNativePG] and [Tembo Cloud]. diff --git a/docker-bake.hcl b/docker-bake.hcl index 81103e9..82df67e 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -49,12 +49,12 @@ variable os_spec { noble = { image = "quay.io/tembo/ubuntu:24.04", digest = "72297848456d5d37d1262630108ab308d3e9ec7ed1c3286a32fe09856619a782" - packages = "libicu74 libllvm19 libpython3.12 libperl5.38" + packages = "libicu74" }, jammy = { image = "quay.io/tembo/ubuntu:22.04", digest = "ed1544e454989078f5dec1bfdabd8c5cc9c48e0705d07b678ab6ae3fb61952d2" - packages = "libicu70 libllvm15 libpython3.11 libperl5.34" + packages = "libicu70" } } } diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index e14ae5a..480c662 100755 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -24,15 +24,24 @@ main() { chmod 700 "$PGDATA" || : if [ ! -s "$PGDATA/PG_VERSION" ]; then - VERSION="$(pg_config --version)" - VERSION="${VERSION%.*}" - if [ "${VERSION#* }" -ge 17 ]; then - # Prefer C.UTF-8. - initdb -D "$PGDATA" -U postgres -c listen_addresses='*' --auth=trust --locale-provider builtin --builtin-locale C.UTF-8 --encoding UNICODE + opts=( + -D "$PGDATA" + -U postgres + -c listen_addresses='*' + -c dynamic_library_path="\$libdir:/var/lib/postgresql/tembo/mod" + --auth trust + --encoding UNICODE + ) + + if [ "$(pg_config --version | perl -ne '/(\d+)/ & print $1')" -ge 17 ]; then + # Prefer builtin C.UTF-8. + opts+=(--locale-provider builtin --builtin-locale C.UTF-8) else # Default to en_US.UTF-8. - initdb -D "$PGDATA" -U postgres -c listen_addresses='*' --auth=trust --locale en_US.UTF-8 --encoding UNICODE + opts+=(--locale en_US.UTF-8) fi + + initdb "${opts[@]}" fi # Start the server. Logs go to STDOUT.