Compare commits

..

4 Commits

Author SHA1 Message Date
eb6e4efca9 refactor layout
python extensions are built using strictly versioned libpq-dev
2025-08-29 02:13:51 +03:00
c8b15861d9 major upgrade
except citus - no packages for Debian 13 yet
2025-08-15 17:02:15 +03:00
af04718692 update/refactor 2025-05-25 12:48:57 +03:00
91d3a48177 update deps 2025-04-09 14:46:16 +03:00
16 changed files with 384 additions and 321 deletions

View File

@@ -1,11 +1,11 @@
ARG UPSTREAM_IMAGE_VERSION ARG UPSTREAM_IMAGE_VERSION
ARG DEPS_IMAGE ARG BASE_IMAGE
FROM docker.io/library/postgres:${UPSTREAM_IMAGE_VERSION}-bookworm AS postgresql-upstream FROM docker.io/library/postgres:${UPSTREAM_IMAGE_VERSION}-trixie AS postgresql-upstream
FROM ${DEPS_IMAGE} AS deps FROM ${BASE_IMAGE} AS base
## --- ## ---
FROM deps AS postgresql FROM base AS postgresql
SHELL [ "/bin/sh", "-ec" ] SHELL [ "/bin/sh", "-ec" ]
COPY /scripts/* /usr/local/sbin/ COPY /scripts/* /usr/local/sbin/
@@ -22,7 +22,9 @@ RUN echo "postgres:x:${PG_UID}:${PG_GID}:postgres:${PGHOME}:/bin/bash" >> /etc/p
RUN install -d -o postgres -g postgres -m 3755 /run/postgresql RUN install -d -o postgres -g postgres -m 3755 /run/postgresql
VOLUME [ "/run/postgresql" ] VOLUME [ "/run/postgresql" ]
COPY /apt/sources.pgdg /etc/apt/sources.list.d/pgdg.sources
COPY /apt/sources.pgdg-ver.in /tmp/pgdg-ver.sources COPY /apt/sources.pgdg-ver.in /tmp/pgdg-ver.sources
COPY /apt/preferences.pgdg /etc/apt/preferences.d/pgdg
COPY /apt/preferences.pgdg-ver.in /tmp/pgdg-ver.prefs COPY /apt/preferences.pgdg-ver.in /tmp/pgdg-ver.prefs
RUN sed "s/%{PG_MAJOR}/${PG_MAJOR}/g" < /tmp/pgdg-ver.sources > "/etc/apt/sources.list.d/pgdg-${PG_MAJOR}.sources" ; \ RUN sed "s/%{PG_MAJOR}/${PG_MAJOR}/g" < /tmp/pgdg-ver.sources > "/etc/apt/sources.list.d/pgdg-${PG_MAJOR}.sources" ; \
sed "s/%{PG_MAJOR}/${PG_MAJOR}/g" < /tmp/pgdg-ver.prefs > "/etc/apt/preferences.d/pgdg-${PG_MAJOR}" ; \ sed "s/%{PG_MAJOR}/${PG_MAJOR}/g" < /tmp/pgdg-ver.prefs > "/etc/apt/preferences.d/pgdg-${PG_MAJOR}" ; \
@@ -48,7 +50,135 @@ RUN ln -sv /usr/local/sbin/dumb-run-as.sh /usr/local/bin/gosu
## --- ## ---
FROM postgresql AS postgresql-extras FROM postgresql AS pybuild
SHELL [ "/bin/sh", "-ec" ]
COPY /scripts/* /usr/local/sbin/
COPY /requirements.txt /tmp/
ENV DEV_PACKAGES='libffi-dev libpq-dev libyaml-dev'
# psutil
ENV CIBUILDWHEEL=1
# pyyaml
ENV PYYAML_FORCE_CYTHON=1
RUN w=$(mktemp -d) ; : "${w:?}" ; \
{ apt-mark showauto ; apt-mark showmanual ; } | sort -uV > "$w/t0" ; \
printf '%s\n' ${DEV_PACKAGES} | sort -uV > "$w/t1" ; \
apt-install.sh ${DEV_PACKAGES} ; \
{ apt-mark showauto ; apt-mark showmanual ; } | sort -uV > "$w/t2" ; \
set +e ; \
grep -Fxv -f "$w/t0" "$w/t2" > "$w/t3" ; \
grep -Fxv -f "$w/t1" "$w/t3" > "$w/t4" ; \
grep -Ev -e '-(dev|doc)$' "$w/t4" > "${PYTHON_SITE_PACKAGES}/apt-deps.txt" ; \
set -e ; \
rm -rf "$w/" ; unset w ; \
apt-install.sh build-essential ; \
pip-env.sh pip install 'cython~=3.1.3' ; \
pip-env.sh pip install \
--no-binary 'cffi,psutil,pyyaml' \
-r /tmp/requirements.txt \
; \
pip-env.sh pip uninstall -y 'cython' ; \
python-rm-cache.sh /usr/local ; \
rm -rf \
/usr/local/bin/patroni_aws \
/usr/local/bin/patroni_raft_controller \
"${PYTHON_SITE_PACKAGES}/etcd/tests" \
"${PYTHON_SITE_PACKAGES}/netaddr/tests" \
"${PYTHON_SITE_PACKAGES}/psutil/tests" \
; \
truncate -s 0 \
"${PYTHON_SITE_PACKAGES}/netaddr/eui/iab.idx" \
"${PYTHON_SITE_PACKAGES}/netaddr/eui/iab.txt" \
"${PYTHON_SITE_PACKAGES}/netaddr/eui/oui.txt" \
"${PYTHON_SITE_PACKAGES}/netaddr/eui/oui.idx" \
; \
find "${PYTHON_SITE_PACKAGES}/" -type f -name '*.so*' -exec ls -l {} + ; \
echo ; \
find "${PYTHON_SITE_PACKAGES}/" -type f -name '*.so*' -printf '%p\0' \
| sed -zE '/rust/d' \
| xargs -0r strip --strip-debug --strip-unneeded ; \
echo ; \
find "${PYTHON_SITE_PACKAGES}/" -type f -name '*.so*' -exec ls -l {} + ; \
apt-remove.sh build-essential ; \
apt-clean.sh
## avoid changing already present packages
RUN rm -rfv \
/usr/local/bin/pip \
/usr/local/bin/pip3* \
; \
find "${PYTHON_SITE_PACKAGES}/" -mindepth 1 -maxdepth 1 -printf '%P\0' \
| sed -zEn \
-e '/^pip(|-.+\.dist-info)$/p' \
| env -C "${PYTHON_SITE_PACKAGES}" xargs -0r rm -rf
## ---
FROM pybuild AS pycache
SHELL [ "/bin/sh", "-ec" ]
COPY /scripts/* /usr/local/sbin/
ENV PYTHONDONTWRITEBYTECODE=''
## Python cache preseed
RUN libpython="${PYTHON_SITE_PACKAGES%/*}" ; \
find "${libpython}/" -mindepth 1 -maxdepth 1 -printf '%P\0' \
| sed -zEn \
-e '/^(asyncio|collections|concurrent|ctypes|email|encodings|html|http|importlib|json|logging|multiprocessing|re|urllib|zipfile|zoneinfo)$/p' \
| sort -zV \
| env -C "${libpython}" xargs -0r \
python3 -m compileall -q -j 2 ; \
find "${PYTHON_SITE_PACKAGES}/" -mindepth 1 -maxdepth 1 -printf '%P\0' \
| sed -zE \
-e '/\.(dist-info|pth|so|txt)$/d' \
-e '/^pip$/d' \
| sort -zV \
| env -C "${PYTHON_SITE_PACKAGES}" xargs -0r \
python3 -m compileall -q -j 2
## Python cache warmup
RUN export PYTHONPROFILEIMPORTTIME=1 ; \
patroni --help ; \
patronictl --help ; \
patroni_barman --help ; \
patroni_wale_restore --help ; \
cdiff --help ; \
netaddr --help ; \
ydiff --help
## Python cache adjustments
RUN d="@$(date '+%s')" ; \
find /usr/local/lib/ -name '*.pyc' -exec touch -m -d "$d" {} + ; \
find /usr/local/lib/ -name __pycache__ -exec touch -m -d "$d" {} +
WORKDIR /pycache
RUN find /usr/local/ -type f -name '*.py[co]' -printf '%P\0' \
| sort -zV \
| tar -C /usr/local --null -T - -cf - \
| tar -xf -
## ---
FROM postgresql AS postgresql-patroni
COPY --from=pybuild /usr/local/bin/ /usr/local/bin/
COPY --from=pybuild /${PYTHON_SITE_PACKAGES}/ /${PYTHON_SITE_PACKAGES}/
COPY --from=pycache /pycache/ /usr/local/
## install missing dependencies for Python site-packages
RUN f="${PYTHON_SITE_PACKAGES}/apt-deps.txt" ; \
[ -s "$f" ] || exit 0 ; \
xargs -a "$f" apt-install.sh ; \
apt-clean.sh
## ---
FROM postgresql-patroni AS postgresql-extras
SHELL [ "/bin/sh", "-ec" ] SHELL [ "/bin/sh", "-ec" ]
RUN apt-install.sh \ RUN apt-install.sh \
@@ -84,8 +214,7 @@ RUN apt-install.sh \
"postgresql-${PG_MAJOR}-unit" \ "postgresql-${PG_MAJOR}-unit" \
"postgresql-${PG_MAJOR}-wal2json" \ "postgresql-${PG_MAJOR}-wal2json" \
; \ ; \
apt-clean.sh ; \ apt-clean.sh
jdupes -1LSpr /usr/
## --- ## ---
@@ -100,14 +229,15 @@ RUN apt-env.sh apt-get update ; \
apt-install.sh \ apt-install.sh \
"${citus_pkg}" \ "${citus_pkg}" \
"postgresql-${PG_MAJOR}-topn" \ "postgresql-${PG_MAJOR}-topn" \
; apt-clean.sh ; \ ; apt-clean.sh
jdupes -1LSpr /usr/
VOLUME [ "${PGHOME}" ] VOLUME [ "${PGHOME}" ]
## --- ## ---
FROM citus ## TODO: disabled until citus packages are ready for Debian 13
# FROM citus
FROM postgresql-extras
SHELL [ "/bin/sh", "-ec" ] SHELL [ "/bin/sh", "-ec" ]
COPY /Dockerfile /usr/local/share/ COPY /Dockerfile /usr/local/share/
@@ -123,8 +253,7 @@ WORKDIR "${PGHOME}"
## NB: override to SIGTERM in order to switch to "Smart Shutdown mode" ## NB: override to SIGTERM in order to switch to "Smart Shutdown mode"
STOPSIGNAL SIGINT STOPSIGNAL SIGINT
ENV DUMB_INIT_SETSID=0 \ ENV MALLOC_ARENA_MAX=4 \
MALLOC_ARENA_MAX=4 \
GOMAXPROCS=4 GOMAXPROCS=4
ENTRYPOINT [ "ep.sh" ] ENTRYPOINT [ "ep.sh" ]

View File

@@ -1,11 +1,9 @@
ARG PYTHONTAG=3.12.9-slim-bookworm ARG PYTHONTAG=3.12.11-slim-trixie
FROM docker.io/python:${PYTHONTAG} AS base-upstream FROM docker.io/python:${PYTHONTAG} AS base-upstream
FROM base-upstream AS base-intermediate FROM base-upstream AS base-intermediate
SHELL [ "/bin/sh", "-ec" ] SHELL [ "/bin/sh", "-ec" ]
COPY /Dockerfile.base /usr/local/share/
COPY /scripts/* /usr/local/sbin/ COPY /scripts/* /usr/local/sbin/
COPY /extra-scripts/* /usr/local/sbin/ COPY /extra-scripts/* /usr/local/sbin/
@@ -20,13 +18,7 @@ ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin \
PYTHONUNBUFFERED=1 \ PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 PYTHONDONTWRITEBYTECODE=1
## local development COPY /apt/sources.debian /etc/apt/sources.list.d/debian.sources
# ENV PIP_INDEX="http://127.0.0.1:8081/repository/proxy_pypi/pypi/" \
# PIP_INDEX_URL="http://127.0.0.1:8081/repository/proxy_pypi/simple/" \
# PIP_TRUSTED_HOST="localhost"
COPY /apt/preferences.backports /etc/apt/preferences.d/backports
COPY /apt/sources.debian /etc/apt/sources.list.d/debian.sources
## prevent services from auto-starting, part 1 ## prevent services from auto-starting, part 1
RUN s='/usr/sbin/policy-rc.d' ; b='/usr/bin/policy-rc.d' ; \ RUN s='/usr/sbin/policy-rc.d' ; b='/usr/bin/policy-rc.d' ; \
@@ -52,10 +44,10 @@ RUN apt-env.sh apt-get update ; \
; \ ; \
apt-env.sh apt-get upgrade -y ; \ apt-env.sh apt-get upgrade -y ; \
apt-install.sh \ apt-install.sh \
apt-utils \
brotli \ brotli \
cron \ cron \
curl \ curl \
dumb-init \
file \ file \
gettext-base \ gettext-base \
gnupg \ gnupg \
@@ -64,6 +56,7 @@ RUN apt-env.sh apt-get update ; \
jdupes \ jdupes \
jq \ jq \
less \ less \
libcap2-bin \
libnss-wrapper \ libnss-wrapper \
logrotate \ logrotate \
lsof \ lsof \
@@ -73,18 +66,32 @@ RUN apt-env.sh apt-get update ; \
openssl \ openssl \
procps \ procps \
psmisc \ psmisc \
systemd-standalone-sysusers \
tzdata \ tzdata \
vim \ vim \
xxd \ xxd \
xz-utils \ xz-utils \
zstd \ zstd \
; \ ; \
apt-clean.sh apt-clean.sh ; \
## remove broken symlinks
find /etc/ -xdev -follow -type l -ls -delete
## perl-base: hardlink->symlink ## perl-base: hardlink->symlink
RUN d=/usr/bin ; \ RUN set +e ; \
find "$d/" -wholename "$d/perl5*" -exec ln -fsv perl {} ';' ; \ d=/usr/bin ; \
ls -li "$d/perl"* ls -li "$d/perl" ; \
find "$d/" -xdev -samefile "$d/perl" 2>/dev/null \
| grep -Fxv -e "$d/perl" \
| while read -r p ; do \
[ -n "$p" ] || continue ; \
[ -e "$p" ] || continue ; \
ls -li "$p" ; \
rm -fv "$p" ; \
ln -fsv perl "$p" ; \
ls -li "$p" ; \
echo ; \
done
## remove unwanted binaries ## remove unwanted binaries
RUN set -f ; \ RUN set -f ; \
@@ -194,101 +201,84 @@ RUN set -f ; \
'write.*' \ 'write.*' \
zramctl \ zramctl \
; do \ ; do \
for d in /usr/sbin /usr/bin /sbin /bin ; do \ ## try dpkg-divert first
find "$d/" ! -type d -wholename "$d/$i" \ for d in /usr/sbin /usr/bin ; do \
| while read -r p ; do \ find "$d/" ! -type d -wholename "$d/$i" ; \
[ -n "$p" ] || continue ; \ done \
[ -e "$p" ] || continue ; \ | while read -r p ; do \
dpkg -S "$p" >/dev/null 2>&1 || continue ; \ [ -n "$p" ] || continue ; \
divert-rm.sh "$p" ; \ [ -e "$p" ] || continue ; \
done ; \ dpkg-search.sh "$p" || continue ; \
done \
| sed -E '/^diversion by/d' \
| sort -uV \
| while read -r pkg path ; do \
[ -n "${pkg}" ] || continue ; \
[ -e "${path}" ] || continue ; \
divert-rm.sh "${path}" ; \
done ; \ done ; \
for d in /usr/sbin /usr/bin /sbin /bin ; do \ ## remove if still exists
find "$d/" ! -type d -wholename "$d/$i" \ for d in /usr/sbin /usr/bin ; do \
| while read -r p ; do \ find "$d/" ! -type d -wholename "$d/$i" ; \
[ -n "$p" ] || continue ; \ done \
[ -e "$p" ] || continue ; \ | while read -r p ; do \
rm -fv "$p" ; \ [ -n "$p" ] || continue ; \
done ; \ [ -e "$p" ] || continue ; \
rm -fv "$p" ; \
done ; \ done ; \
done ; \ done ; \
## fixup ## remove broken symlinks
rm -f \ find /bin/ /sbin/ -xdev -follow -type l -ls -delete
/bin/lastb \
/bin/sg \
/sbin/getty \
; :
## remove excessive privileges from binaries ## remove excessive privileges from binaries: setuid/setgid
RUN set -f ; \ RUN find / -xdev -type f -perm /7000 \
for i in \ | sort -V \
passwd \ | while read -r p ; do \
su \ [ -n "$p" ] || continue ; \
; do \ ## clear setuid/setgid bit
for d in /usr/sbin /usr/bin /sbin /bin ; do \ m=$(env stat -c '0%a' "$p") ; \
find "$d/" ! -type d -wholename "$d/$i" \ m=$(printf '0%o\n' $((m & 00777)) ) ; \
| while read -r p ; do \ ## try to lookup in dpkg database
[ -n "$p" ] || continue ; \ n=$(set +e ; dpkg-search.sh "$p" | sed -E '/^diversion by/d' | cut -d ' ' -f2-) ; \
[ -e "$p" ] || continue ; \ ls -l "$p" ; \
dpkg -S "$p" >/dev/null 2>&1 || continue ; \ if [ "$p" = "$n" ] ; then \
o=$(env stat -c '%U' "$p") ; \ o=$(env stat -c '%U' "$n") ; \
g=$(env stat -c '%G' "$p") ; \ g=$(env stat -c '%G' "$n") ; \
ls -l "$p" ; \ dpkg-statoverride --force --update --add "$o" "$g" "$m" "$n" ; \
dpkg-statoverride --update --add "$o" "$g" 0755 "$p" ; \ else \
ls -l "$p" ; \ env printf 'unable to find in dpkg database: %q\n' "$n" ; \
done ; \ chmod "$m" "$p" ; \
done ; \ fi ; \
ls -l "$p" ; \
done
## remove excessive privileges from binaries: setcap
RUN find / -xdev -type f -executable -exec getcap {} + \
| sort -V \
| while read -r path caps ; do \
[ -n "${path}" ] || continue ; \
if [ "${path}" = /usr/bin/ping ] ; then continue ; fi ; \
getcap -v "${path}" ; \
setcap -r "${path}" "${caps}" 2>/dev/null || : ; \
getcap -v "${path}" ; \
done done
## "docker.io/python"-specific cleanup ## "docker.io/python"-specific cleanup
RUN env -C /root rm -f .bash_history .python_history .wget-hsts RUN env -C /root rm -f .bash_history .python_history .wget-hsts
RUN pip-env.sh pip list --format freeze \
| grep -F '==' | awk -F= '{print $1}' \
| xargs -r pip-env.sh pip install -U ; \
python-rm-cache.sh "${PYTHON_SITE_PACKAGES}"
RUN libpython="${PYTHON_SITE_PACKAGES%/*}" ; \
rm -rfv \
/usr/local/bin/idle* \
/usr/local/bin/pydoc* \
"${libpython}/ensurepip/_bundled" \
"${libpython}/idlelib" \
"${libpython}/pydoc.py" \
"${libpython}/pydoc_data" \
"${libpython}/tkinter" \
"${libpython}/turtle.py" \
"${libpython}/turtledemo" \
; \
find "${PYTHON_SITE_PACKAGES}/" -iname '*.exe' -ls -delete ; \
python-rm-cache.sh /usr/local
## adjust pip/certifi
RUN certifi_pem="${PYTHON_SITE_PACKAGES}/pip/_vendor/certifi/cacert.pem" ; \
rm -f "${certifi_pem}" ; \
ln -s /etc/ssl/certs/ca-certificates.crt "${certifi_pem}"
RUN find /usr/local/sbin/ ! -type d -ls -delete ; \
find /run/ -mindepth 1 -ls -delete || : ; \
install -d -m 01777 /run/lock ; \
jdupes -1LSpr /usr/
## --- ## ---
FROM base-intermediate AS certs FROM base-intermediate AS certs
SHELL [ "/bin/sh", "-ec" ] SHELL [ "/bin/sh", "-ec" ]
COPY /scripts/* /usr/local/sbin/ ## "2025.08.03"
COPY /extra-scripts/* /usr/local/sbin/ ENV CERTIFI_COMMIT=a97d9ad8f87c382378dddc0b0b33b9770932404e
## "2025.01.31"
ENV CERTIFI_COMMIT=088f93122ea7c91cfdaeea7fa76ab2f850b8064d
# 'https://raw.githubusercontent.com/certifi/python-certifi' # 'https://raw.githubusercontent.com/certifi/python-certifi'
ARG CERTIFI_BASE_URI='https://github.com/certifi/python-certifi/raw' ARG CERTIFI_BASE_URI='https://github.com/certifi/python-certifi/raw'
ARG CERTIFI_URI="${CERTIFI_BASE_URI}/${CERTIFI_COMMIT}/certifi/cacert.pem" ARG CERTIFI_URI="${CERTIFI_BASE_URI}/${CERTIFI_COMMIT}/certifi/cacert.pem"
ADD "${CERTIFI_URI}" /tmp/certifi.crt ADD "${CERTIFI_URI}" /tmp/certifi.crt
RUN apt-install.sh ca-certificates ; \ RUN apt-install.sh ca-certificates ; \
apt-clean.sh ; \ apt-clean.sh ; \
@@ -306,9 +296,6 @@ RUN apt-install.sh ca-certificates ; \
FROM base-intermediate AS apt-gpg FROM base-intermediate AS apt-gpg
SHELL [ "/bin/sh", "-ec" ] SHELL [ "/bin/sh", "-ec" ]
COPY /scripts/* /usr/local/sbin/
COPY /extra-scripts/* /usr/local/sbin/
COPY --from=certs /etc/ssl/certs/ca-certificates.* /etc/ssl/certs/ COPY --from=certs /etc/ssl/certs/ca-certificates.* /etc/ssl/certs/
ADD https://apt.postgresql.org/pub/repos/apt/ACCC4CF8.asc /tmp/pgdg.gpg.bin ADD https://apt.postgresql.org/pub/repos/apt/ACCC4CF8.asc /tmp/pgdg.gpg.bin
@@ -322,7 +309,8 @@ RUN pkg='gnupg' ; \
apt-remove.sh ${pkg} apt-remove.sh ${pkg}
COPY /apt/sources.pgdg /etc/apt/sources.list.d/pgdg.sources COPY /apt/sources.pgdg /etc/apt/sources.list.d/pgdg.sources
COPY /apt/sources.citus /etc/apt/sources.list.d/citus.sources ## TODO: disabled until citus packages are ready for Debian 13
# COPY /apt/sources.citus /etc/apt/sources.list.d/citus.sources
## verify sources! ## verify sources!
RUN apt-env.sh apt-get update ; \ RUN apt-env.sh apt-get update ; \
@@ -330,10 +318,117 @@ RUN apt-env.sh apt-get update ; \
## --- ## ---
FROM base-intermediate AS tools
SHELL [ "/bin/sh", "-ec" ]
## current HEAD: "main: don't use secure_getenv", December 14, 2024
ENV CATATONIT_COMMIT=56579adbb42c0c7ad94fc12d844b38fc5b37b3ce
# ARG CATATONIT_BASE_URI='https://codeload.github.com/openSUSE/catatonit/tar.gz'
# ARG CATATONIT_URI="${CATATONIT_BASE_URI}/${CATATONIT_COMMIT}"
ARG CATATONIT_BASE_URI='https://github.com/openSUSE/catatonit/archive'
ARG CATATONIT_URI="${CATATONIT_BASE_URI}/${CATATONIT_COMMIT}.tar.gz"
# hadolint ignore=DL3020
ADD "${CATATONIT_URI}" /tmp/catatonit.tar.gz
RUN pkg='build-essential debhelper musl-dev autoconf autoconf-archive' ; \
apt-install.sh ${pkg} ; \
DEB_HOST_GNU_TYPE=$(dpkg-architecture -q DEB_HOST_GNU_TYPE) ; \
export HOSTCC="${DEB_HOST_GNU_TYPE}-gcc" ; \
DEB_TARGET_GNU_TYPE=$(dpkg-architecture -q DEB_TARGET_GNU_TYPE) ; \
DEB_TARGET_MUSL_TYPE=$(printf '%s' "${DEB_TARGET_GNU_TYPE}" | sed -E 's/-gnu$/-musl/') ; \
CFLAGS_LTO="-flto=2 -fuse-linker-plugin -ffat-lto-objects -flto-partition=none" ; \
CFLAGS_COMMON="-O2 -g -pipe -fPIE -fstack-protector-strong -fstack-clash-protection -fcf-protection" ; \
CPPFLAGS="-Wall -Wextra -Werror=format-security -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2" ; \
## build catatonit
d=/tmp/catatonit ; \
rm -rf "$d" ; \
mkdir -p "$d" ; \
( \
cd "$d" ; \
tar --strip-components=1 -xf /tmp/catatonit.tar.gz ; \
commit_abbrev=$(printf '%s' "${CATATONIT_COMMIT}" | cut -c1-8) ; \
sed -i "s/+dev/+git.${commit_abbrev}/" configure.ac ; \
export CC="${DEB_TARGET_MUSL_TYPE}-gcc" ; \
export CFLAGS="${CFLAGS_LTO} ${CFLAGS_COMMON} ${CPPFLAGS}" ; \
export LDFLAGS="-static-pie -Wl,-z,relro -Wl,-z,now" ; \
autoreconf -fiv ; \
./configure ; \
make -j1 ; \
ls -l catatonit ; \
# "${DEB_TARGET_GNU_TYPE}-strip" --strip-debug --strip-unneeded catatonit ; \
strip --strip-debug --strip-unneeded catatonit ; \
ls -l catatonit ; \
cp catatonit /usr/local/bin/ ; \
) ; \
## cleanup
rm -rf "$d" ; \
apt-remove.sh ${pkg} ; \
apt-clean.sh
## ---
FROM base-intermediate AS base FROM base-intermediate AS base
SHELL [ "/bin/sh", "-ec" ]
COPY /Dockerfile.base /usr/local/share/
COPY --from=certs /etc/ssl/certs/ca-certificates.* /etc/ssl/certs/ COPY --from=certs /etc/ssl/certs/ca-certificates.* /etc/ssl/certs/
COPY --from=apt-gpg /etc/apt/keyrings/ /etc/apt/keyrings/ COPY --from=apt-gpg /etc/apt/keyrings/ /etc/apt/keyrings/
COPY --from=tools /usr/local/bin/catatonit /usr/local/bin/
RUN python-rm-cache.sh /usr/local
RUN pip-env.sh pip list --format freeze \
| grep -F '==' | awk -F= '{print $1}' \
| xargs -r pip-env.sh pip install -U ; \
python-rm-cache.sh /usr/local
RUN libpython="${PYTHON_SITE_PACKAGES%/*}" ; \
rm -rfv \
/usr/local/bin/idle* \
/usr/local/bin/pydoc* \
"${libpython}/ensurepip/_bundled" \
"${libpython}/idlelib" \
"${libpython}/pydoc.py" \
"${libpython}/pydoc_data" \
"${libpython}/tkinter" \
"${libpython}/turtle.py" \
"${libpython}/turtledemo" \
; \
find "${PYTHON_SITE_PACKAGES}/" -iname '*.exe' -ls -delete
## adjust pip/certifi
RUN certifi_pem="${PYTHON_SITE_PACKAGES}/pip/_vendor/certifi/cacert.pem" ; \
[ -d "${certifi_pem%/*}" ] || exit 0 ; \
rm -f "${certifi_pem}" ; \
ln -sv /etc/ssl/certs/ca-certificates.crt "${certifi_pem}"
## set up locales!
RUN _lang=en_US.UTF8 ; \
{ \
echo "locales locales/default_environment_locale select ${LANG}" ; \
echo "locales locales/locales_to_be_generated multiselect ${LANG} UTF-8" ; \
} | debconf-set-selections ; \
f=/etc/dpkg/dpkg.cfg.d/docker ; \
if [ -f "$f" ] ; then \
sed -Ei '/\/usr\/share\/locale/d' "$f" ; \
fi ; \
echo "LANG=${_lang}" > /etc/default/locale ; \
apt-install.sh locales ; apt-clean.sh ; \
grep -Fixq "${_lang} UTF-8" /etc/locale.gen || { \
echo "${_lang} UTF-8" >> /etc/locale.gen ; \
locale-gen ; \
} ; \
locale -a | grep -Fixq "${_lang}"
ENV LANG=en_US.UTF8
RUN find /usr/local/sbin/ ! -type d -ls -delete ; \
find /run/ -mindepth 1 -ls -delete || : ; \
install -d -m 01777 /run/lock ; \
jdupes -1LSpr /usr/
ENTRYPOINT [ ] ENTRYPOINT [ ]
CMD [ "bash" ] CMD [ "bash" ]

View File

@@ -1,164 +0,0 @@
ARG BASE_IMAGE
FROM ${BASE_IMAGE} AS base
## ---
FROM base AS patroni
SHELL [ "/bin/sh", "-ec" ]
COPY /scripts/* /usr/local/sbin/
COPY /apt/sources.pgdg /etc/apt/sources.list.d/pgdg.sources
COPY /apt/preferences.pgdg /etc/apt/preferences.d/pgdg
COPY /requirements.txt /tmp/
ENV DEV_PACKAGES='libffi-dev libpq-dev libyaml-dev'
# psutil
ENV CIBUILDWHEEL=1
# pyyaml
ENV PYYAML_FORCE_CYTHON=1
RUN w=$(mktemp -d) ; : "${w:?}" ; \
{ apt-mark showauto ; apt-mark showmanual ; } | sort -uV > "$w/t0" ; \
printf '%s\n' ${DEV_PACKAGES} | sort -uV > "$w/t1" ; \
apt-install.sh ${DEV_PACKAGES} ; \
{ apt-mark showauto ; apt-mark showmanual ; } | sort -uV > "$w/t2" ; \
set +e ; \
grep -Fxv -f "$w/t0" "$w/t2" > "$w/t3" ; \
grep -Fxv -f "$w/t1" "$w/t3" > "$w/t4" ; \
grep -Ev -e '-(dev|doc)$' "$w/t4" > "${PYTHON_SITE_PACKAGES}/apt-deps.txt" ; \
set -e ; \
rm -rf "$w/" ; unset w ; \
apt-install.sh build-essential ; \
pip-env.sh pip install 'cython' ; \
pip-env.sh pip install \
--no-binary 'cffi,psutil,pyyaml' \
-r /tmp/requirements.txt \
; \
pip-env.sh pip uninstall -y 'cython' ; \
python-rm-cache.sh /usr/local ; \
rm -rf \
/usr/local/bin/patroni_aws \
/usr/local/bin/patroni_raft_controller \
"${PYTHON_SITE_PACKAGES}/etcd/tests" \
"${PYTHON_SITE_PACKAGES}/netaddr/tests" \
"${PYTHON_SITE_PACKAGES}/psutil/tests" \
; \
truncate -s 0 \
"${PYTHON_SITE_PACKAGES}/netaddr/eui/iab.idx" \
"${PYTHON_SITE_PACKAGES}/netaddr/eui/iab.txt" \
"${PYTHON_SITE_PACKAGES}/netaddr/eui/oui.txt" \
"${PYTHON_SITE_PACKAGES}/netaddr/eui/oui.idx" \
; \
find "${PYTHON_SITE_PACKAGES}/" -type f -name '*.so*' -exec ls -l {} + ; \
echo ; \
find "${PYTHON_SITE_PACKAGES}/" -type f -name '*.so*' -printf '%p\0' \
| sed -zE '/rust/d' \
| xargs -0r strip --verbose --strip-debug --strip-unneeded ; \
echo ; \
find "${PYTHON_SITE_PACKAGES}/" -type f -name '*.so*' -exec ls -l {} + ; \
apt-remove.sh build-essential ; \
apt-clean.sh
## avoid changing already present packages
RUN find "${PYTHON_SITE_PACKAGES}/" -mindepth 1 -maxdepth 1 -printf '%P\0' \
| sed -zEn \
-e '/^pip(|-.+\.dist-info)$/p' \
| env -C "${PYTHON_SITE_PACKAGES}" xargs -0r \
rm -rf
## ---
FROM base AS deps-intermediate
SHELL [ "/bin/sh", "-ec" ]
COPY /Dockerfile.deps /usr/local/share/
COPY /scripts/* /usr/local/sbin/
COPY /apt/sources.pgdg /etc/apt/sources.list.d/pgdg.sources
COPY /apt/preferences.pgdg /etc/apt/preferences.d/pgdg
COPY --from=patroni /usr/local/bin/ /usr/local/bin/
COPY --from=patroni /${PYTHON_SITE_PACKAGES}/ /${PYTHON_SITE_PACKAGES}/
## install missing dependencies for Python site-packages
RUN f="${PYTHON_SITE_PACKAGES}/apt-deps.txt" ; \
[ -s "$f" ] || exit 0 ; \
xargs -a "$f" apt-install.sh ; \
apt-clean.sh
## set up locales!
RUN _lang=en_US.UTF8 ; \
{ \
echo "locales locales/default_environment_locale select ${LANG}" ; \
echo "locales locales/locales_to_be_generated multiselect ${LANG} UTF-8" ; \
} | debconf-set-selections ; \
f=/etc/dpkg/dpkg.cfg.d/docker ; \
if [ -f "$f" ] ; then \
sed -Ei '/\/usr\/share\/locale/d' "$f" ; \
fi ; \
echo "LANG=${_lang}" > /etc/default/locale ; \
apt-install.sh locales ; apt-clean.sh ; \
grep -Fixq "${_lang} UTF-8" /etc/locale.gen || { \
echo "${_lang} UTF-8" >> /etc/locale.gen ; \
locale-gen ; \
} ; \
locale -a | grep -Fixq "${_lang}"
ENV LANG=en_US.UTF8
RUN find /usr/local/sbin/ ! -type d -ls -delete ; \
jdupes -1LSpr /usr/
## ---
FROM deps-intermediate AS pycache
SHELL [ "/bin/sh", "-ec" ]
COPY /scripts/* /usr/local/sbin/
ENV PYTHONDONTWRITEBYTECODE=''
## Python cache preseed
RUN libpython="${PYTHON_SITE_PACKAGES%/*}" ; \
find "${libpython}/" -mindepth 1 -maxdepth 1 -printf '%P\0' \
| sed -zEn \
-e '/^(asyncio|collections|concurrent|ctypes|email|encodings|html|http|importlib|json|logging|multiprocessing|re|urllib|zipfile|zoneinfo)$/p' \
| sort -zV \
| env -C "${libpython}" xargs -0r \
python3 -m compileall -q -j 2 ; \
find "${PYTHON_SITE_PACKAGES}/" -mindepth 1 -maxdepth 1 -printf '%P\0' \
| sed -zE \
-e '/\.(dist-info|pth|so|txt)$/d' \
-e '/^pip$/d' \
| sort -zV \
| env -C "${PYTHON_SITE_PACKAGES}" xargs -0r \
python3 -m compileall -q -j 2
## Python cache warmup
RUN export PYTHONPROFILEIMPORTTIME=1 ; \
patroni --help ; \
patronictl --help ; \
patroni_barman --help ; \
patroni_wale_restore --help ; \
cdiff --help ; \
netaddr --help ; \
ydiff --help
## Python cache adjustments
RUN d="@$(date '+%s')" ; \
find /usr/local/lib/ -name '*.pyc' -exec touch -m -d "$d" {} + ; \
find /usr/local/lib/ -name __pycache__ -exec touch -m -d "$d" {} +
WORKDIR /pycache
RUN find /usr/local/ -type f -name '*.py[co]' -printf '%P\0' \
| sort -zV \
| tar -C /usr/local --null -T - -cf - \
| tar -xf -
FROM deps-intermediate AS deps
## RFC: Python cache
COPY --from=pycache /pycache/ /usr/local/

View File

@@ -1,4 +0,0 @@
## example:
# Package: src:curl
# Pin: release n=bookworm-backports
# Pin-Priority: 600

View File

@@ -1,3 +1,3 @@
Package: * Package: *
Pin: release a=bookworm-pgdg Pin: release a=trixie-pgdg
Pin-Priority: 600 Pin-Priority: 600

View File

@@ -1,3 +1,3 @@
Package: src:postgresql-%{PG_MAJOR} Package: src:postgresql-%{PG_MAJOR}
Pin: release a=bookworm-pgdg Pin: release a=trixie-pgdg
Pin-Priority: 650 Pin-Priority: 650

View File

@@ -1,5 +1,5 @@
Types: deb Types: deb
URIs: https://packagecloud.io/citusdata/community/debian/ URIs: https://packagecloud.io/citusdata/community/debian/
Suites: bookworm Suites: trixie
Components: main Components: main
Signed-By: /etc/apt/keyrings/citus.gpg.asc Signed-By: /etc/apt/keyrings/citus.gpg.asc

View File

@@ -1,11 +1,11 @@
Types: deb Types: deb
URIs: http://deb.debian.org/debian URIs: http://deb.debian.org/debian
Suites: bookworm bookworm-updates bookworm-proposed-updates bookworm-backports Suites: trixie trixie-updates trixie-proposed-updates trixie-backports
Components: main Components: main
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
Types: deb Types: deb
URIs: http://deb.debian.org/debian-security URIs: http://deb.debian.org/debian-security
Suites: bookworm-security Suites: trixie-security
Components: main Components: main
Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg

View File

@@ -1,5 +1,5 @@
Types: deb Types: deb
URIs: http://apt.postgresql.org/pub/repos/apt/ URIs: http://apt.postgresql.org/pub/repos/apt/
Suites: bookworm-pgdg Suites: trixie-pgdg
Components: main Components: main
Signed-By: /etc/apt/keyrings/pgdg.gpg.asc Signed-By: /etc/apt/keyrings/pgdg.gpg.asc

View File

@@ -1,5 +1,5 @@
Types: deb Types: deb
URIs: http://apt.postgresql.org/pub/repos/apt/ URIs: http://apt.postgresql.org/pub/repos/apt/
Suites: bookworm-pgdg Suites: trixie-pgdg
Components: %{PG_MAJOR} Components: %{PG_MAJOR}
Signed-By: /etc/apt/keyrings/pgdg.gpg.asc Signed-By: /etc/apt/keyrings/pgdg.gpg.asc

View File

@@ -8,7 +8,7 @@ BUILDAH_ISOLATION="${BUILDAH_ISOLATION:-chroot}"
BUILDAH_NETWORK="${BUILDAH_NETWORK:-host}" BUILDAH_NETWORK="${BUILDAH_NETWORK:-host}"
set +a set +a
PYTHONTAG="${PYTHONTAG:-3.12.9-slim-bookworm}" PYTHONTAG="${PYTHONTAG:-3.12.11-slim-trixie}"
grab_site_packages() { grab_site_packages() {
podman run \ podman run \
@@ -27,7 +27,7 @@ grab_site_packages() {
PYTHON_SITE_PACKAGES=$(grab_site_packages "docker.io/python:${PYTHONTAG}") PYTHON_SITE_PACKAGES=$(grab_site_packages "docker.io/python:${PYTHONTAG}")
[ -n "${PYTHON_SITE_PACKAGES:?}" ] [ -n "${PYTHON_SITE_PACKAGES:?}" ]
img="docker.io/rockdrilla/postgresql:base-v3" img="docker.io/rockdrilla/postgresql:base-v7"
buildah bud \ buildah bud \
-f ./Dockerfile.base \ -f ./Dockerfile.base \

View File

@@ -1,18 +0,0 @@
#!/bin/sh
set -ef
cd "$(dirname "$0")/.."
set -a
BUILDAH_FORMAT="${BUILDAH_FORMAT:-docker}"
BUILDAH_ISOLATION="${BUILDAH_ISOLATION:-chroot}"
BUILDAH_NETWORK="${BUILDAH_NETWORK:-host}"
set +a
img="docker.io/rockdrilla/postgresql:deps-v3"
base="docker.io/rockdrilla/postgresql:base-v3"
exec buildah bud \
-f ./Dockerfile.deps \
-t "${img}" \
--pull=missing --no-cache \
--build-arg "BASE_IMAGE=${base}" \

View File

@@ -8,24 +8,25 @@ BUILDAH_ISOLATION="${BUILDAH_ISOLATION:-chroot}"
BUILDAH_NETWORK="${BUILDAH_NETWORK:-host}" BUILDAH_NETWORK="${BUILDAH_NETWORK:-host}"
set +a set +a
POSTGRESQL_VERSION="${1:-16.7}" POSTGRESQL_VERSION="${1:-17.6}"
PG_MAJOR="${POSTGRESQL_VERSION%%.*}" PG_MAJOR="${POSTGRESQL_VERSION%%.*}"
img="docker.io/rockdrilla/postgresql:${POSTGRESQL_VERSION}" img="docker.io/rockdrilla/postgresql:${POSTGRESQL_VERSION}$2"
deps="docker.io/rockdrilla/postgresql:deps-v3" orig_base="docker.io/rockdrilla/postgresql:base-v7"
base="${orig_base}-${POSTGRESQL_VERSION}-env"
c=$(buildah from --pull=missing "${deps}") c=$(buildah from --pull=missing "${orig_base}")
[ -n "${c:?}" ] [ -n "${c:?}" ]
buildah config --env "POSTGRESQL_VERSION=${POSTGRESQL_VERSION}" "$c" buildah config --env "POSTGRESQL_VERSION=${POSTGRESQL_VERSION}" "$c"
buildah config --env "PG_MAJOR=${PG_MAJOR}" "$c" buildah config --env "PG_MAJOR=${PG_MAJOR}" "$c"
buildah commit --rm "$c" "${img}-env" buildah commit --rm "$c" "${base}"
unset c unset c
buildah bud \ buildah bud \
-f ./Dockerfile \ -f ./Dockerfile \
-t "${img}" \ -t "${img}" \
--pull=missing --no-cache \ --pull=missing --no-cache \
--build-arg "DEPS_IMAGE=${img}-env" \ --build-arg "BASE_IMAGE=${base}" \
--build-arg "UPSTREAM_IMAGE_VERSION=${POSTGRESQL_VERSION}" \ --build-arg "UPSTREAM_IMAGE_VERSION=${POSTGRESQL_VERSION}" \
podman image rm "${img}-env" podman image rm "${base}"

6
ep.sh
View File

@@ -47,11 +47,11 @@ chown -h postgres:postgres "${PGDATA}"
set -e set -e
if [ "$c" = postgres ] ; then if [ "$c" = postgres ] ; then
exec dumb-init docker-entrypoint.sh "$@" exec catatonit -- docker-entrypoint.sh "$@"
fi fi
if [ "$(id -u)" != 0 ] ; then if [ "$(id -u)" != 0 ] ; then
exec dumb-init "$@" exec catatonit -- "$@"
fi fi
exec dumb-run-as.sh postgres dumb-init "$@" exec dumb-run-as.sh postgres catatonit -- "$@"

View File

@@ -1,28 +1,28 @@
## psycopg[c,pool] ## psycopg[c,pool]
psycopg-c==3.2.4 psycopg-c==3.2.9
typing_extensions==4.12.2 typing_extensions==4.15.0
psycopg-pool==3.2.4 psycopg-pool==3.2.6
psycopg[c,pool]==3.2.4 psycopg[c,pool]==3.2.9
## patroni[etcd3,kubernetes] ## patroni[etcd3,kubernetes]
click==8.1.8 click==8.2.1
wcwidth==0.2.13 wcwidth==0.2.13
prettytable==3.14.0 prettytable==3.16.0
psutil==7.0.0 psutil==7.0.0
six==1.17.0 six==1.17.0
python-dateutil==2.9.0.post0 python-dateutil==2.9.0.post0
PyYAML==6.0.2 PyYAML==6.0.2
urllib3==2.3.0 urllib3==2.5.0
ydiff==1.4.2 ydiff==1.4.2
dnspython==2.7.0 dnspython==2.7.0
python-etcd==0.4.5 python-etcd==0.4.5
patroni[etcd3,kubernetes]==4.0.5 patroni[etcd3,kubernetes]==4.0.6
## misc ## misc
cdiff==1.0 cdiff==1.0
pycparser==2.22 pycparser==2.22
cffi==1.17.1 cffi==1.17.1
cryptography==44.0.1 cryptography==45.0.6
netaddr==1.3.0 netaddr==1.3.0

24
scripts/dpkg-search.sh Executable file
View File

@@ -0,0 +1,24 @@
#!/bin/sh
set -ef
: "${1:?}"
if dpkg-query --search "$1" ; then
exit 0
fi
case "$1" in
*\** | *\?* )
env printf '%s does not support globs: %q\n' "${0##*/}" "$1" >&2
exit 1
;;
esac
while read -r f ; do
[ -n "$f" ] || continue
dpkg-query --search "$f" || continue
exit 0
done <<EOF
$(set +e ; find / -xdev -follow -samefile "$1" 2>/dev/null | grep -Fxv -e "$1")
EOF
exit 1