ARG PYTHONTAG=3.12.11-slim-trixie FROM docker.io/python:${PYTHONTAG} AS base-upstream FROM base-upstream AS base-intermediate SHELL [ "/bin/sh", "-ec" ] COPY /scripts/* /usr/local/sbin/ COPY /extra-scripts/* /usr/local/sbin/ ## PATH: remove /sbin and /bin (/usr is merged) ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin \ TMPDIR=/tmp \ LANG=C.UTF-8 \ LC_ALL=C.UTF-8 \ TERM=linux \ TZ=Etc/UTC \ MALLOC_ARENA_MAX=2 \ PYTHONUNBUFFERED=1 \ PYTHONDONTWRITEBYTECODE=1 COPY /apt/sources.debian /etc/apt/sources.list.d/debian.sources ## prevent services from auto-starting, part 1 RUN s='/usr/sbin/policy-rc.d' ; b='/usr/bin/policy-rc.d' ; \ rm -f "$s" "$b" ; \ echo '#!/bin/sh' > "$b" ; \ echo 'exit 101' >> "$b" ; \ chmod 0755 "$b" ; \ ln -s "$b" "$s" RUN divert_true() { divert-rm.sh "$1" ; ln -sv /bin/true "$1" ; } ; \ ## prevent services from auto-starting, part 2 divert_true /sbin/start-stop-daemon ; \ ## always report that we're in chroot divert_true /usr/bin/ischroot ; \ ## hide systemd helpers divert_true /usr/bin/deb-systemd-helper ; \ divert_true /usr/bin/deb-systemd-invoke RUN apt-env.sh apt-get update ; \ apt-remove.sh \ ca-certificates \ e2fsprogs \ ; \ apt-env.sh apt-get upgrade -y ; \ apt-install.sh \ apt-utils \ brotli \ cron \ curl \ file \ gettext-base \ gnupg \ iproute2 \ iputils-ping \ jdupes \ jq \ less \ libcap2-bin \ libnss-wrapper \ logrotate \ lsof \ ncurses-base \ netbase \ netcat-openbsd \ openssl \ procps \ psmisc \ systemd-standalone-sysusers \ tzdata \ vim \ xxd \ xz-utils \ zstd \ ; \ apt-clean.sh ; \ ## remove broken symlinks find /etc/ -xdev -follow -type l -ls -delete ## perl-base: hardlink->symlink RUN set +e ; \ d=/usr/bin ; \ 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 RUN set -f ; \ for i in \ addpart \ apt-ftparchive \ agetty \ badblocks \ blkdiscard \ blkid \ blkzone \ blockdev \ bsd-write \ chage \ chcpu \ chfn \ chgpasswd \ chmem \ chpasswd \ chsh \ cpgr \ cppw \ crontab \ ctrlaltdel \ debugfs \ delpart \ dmesg \ dumpe2fs \ e2freefrag \ e2fsck \ e2image \ e2label \ e2mmpstatus \ e2scrub \ 'e2scrub*' \ e2undo \ e4crypt \ e4defrag \ expiry \ faillock \ fdformat \ fincore \ findfs \ fsck \ 'fsck.*' \ fsfreeze \ fstrim \ getty \ gpasswd \ groupmems \ grpck \ grpconv \ grpunconv \ hwclock \ isosize \ last \ lastb \ ldattach \ losetup \ lsblk \ lsirq \ lslogins \ mcookie \ mesg \ mke2fs \ mkfs \ 'mkfs.*' \ mkhomedir_helper \ mklost+found \ mkswap \ mount \ newgrp \ newusers \ pam-auth-update \ pam_getenv \ pam_namespace_helper \ pam_timestamp_check \ partx \ pivot_root \ pwck \ pwconv \ pwhistory_helper \ pwunconv \ raw \ readprofile \ resize2fs \ resizepart \ rtcwake \ sg \ shadowconfig \ sulogin \ swaplabel \ swapoff \ swapon \ switch_root \ tune2fs \ umount \ unix_chkpwd \ unix_update \ utmpdump \ vigr \ vipw \ wall \ wdctl \ wipefs \ write \ 'write.*' \ zramctl \ ; do \ ## try dpkg-divert first for d in /usr/sbin /usr/bin ; do \ find "$d/" ! -type d -wholename "$d/$i" ; \ done \ | while read -r p ; do \ [ -n "$p" ] || continue ; \ [ -e "$p" ] || continue ; \ 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 ; \ ## remove if still exists for d in /usr/sbin /usr/bin ; do \ find "$d/" ! -type d -wholename "$d/$i" ; \ done \ | while read -r p ; do \ [ -n "$p" ] || continue ; \ [ -e "$p" ] || continue ; \ rm -fv "$p" ; \ done ; \ done ; \ ## remove broken symlinks find /bin/ /sbin/ -xdev -follow -type l -ls -delete ## remove excessive privileges from binaries: setuid/setgid RUN find / -xdev -type f -perm /7000 \ | sort -V \ | while read -r p ; do \ [ -n "$p" ] || continue ; \ ## clear setuid/setgid bit m=$(env stat -c '0%a' "$p") ; \ m=$(printf '0%o\n' $((m & 00777)) ) ; \ ## try to lookup in dpkg database n=$(set +e ; dpkg-search.sh "$p" | sed -E '/^diversion by/d' | cut -d ' ' -f2-) ; \ ls -l "$p" ; \ if [ "$p" = "$n" ] ; then \ o=$(env stat -c '%U' "$n") ; \ g=$(env stat -c '%G' "$n") ; \ dpkg-statoverride --force --update --add "$o" "$g" "$m" "$n" ; \ else \ env printf 'unable to find in dpkg database: %q\n' "$n" ; \ chmod "$m" "$p" ; \ 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 ## "docker.io/python"-specific cleanup RUN env -C /root rm -f .bash_history .python_history .wget-hsts ## --- FROM base-intermediate AS certs SHELL [ "/bin/sh", "-ec" ] ## "2025.08.03" ENV CERTIFI_COMMIT=a97d9ad8f87c382378dddc0b0b33b9770932404e # 'https://raw.githubusercontent.com/certifi/python-certifi' ARG CERTIFI_BASE_URI='https://github.com/certifi/python-certifi/raw' ARG CERTIFI_URI="${CERTIFI_BASE_URI}/${CERTIFI_COMMIT}/certifi/cacert.pem" ADD "${CERTIFI_URI}" /tmp/certifi.crt RUN apt-install.sh ca-certificates ; \ apt-clean.sh ; \ ca_file='/etc/ssl/certs/ca-certificates.crt' ; \ ls -l "${ca_file}" ; \ ## process certifi certifi-extras.sh /tmp/certifi.crt ; \ openssl-cert-auto-pem.sh "${ca_file}" "${ca_file}.new" "${ca_file}.fp" ; \ mv -f "${ca_file}.new" "${ca_file}" ; \ chmod 0444 "${ca_file}" "${ca_file}.fp" ; \ ls -l "${ca_file}" "${ca_file}.fp" ## --- FROM base-intermediate AS apt-gpg SHELL [ "/bin/sh", "-ec" ] 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://packagecloud.io/citusdata/community/gpgkey /tmp/citus.gpg.bin ## process GPG keyrings RUN pkg='gnupg' ; \ apt-install.sh ${pkg} ; \ gpg-export.sh /tmp/pgdg.gpg.bin /etc/apt/keyrings/pgdg.gpg.asc ; \ gpg-export.sh /tmp/citus.gpg.bin /etc/apt/keyrings/citus.gpg.asc ; \ apt-remove.sh ${pkg} COPY /apt/sources.pgdg /etc/apt/sources.list.d/pgdg.sources ## TODO: disabled until citus packages are ready for Debian 13 # COPY /apt/sources.citus /etc/apt/sources.list.d/citus.sources ## verify sources! RUN apt-env.sh apt-get update ; \ apt-clean.sh ## --- 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 SHELL [ "/bin/sh", "-ec" ] COPY /Dockerfile.base /usr/local/share/ COPY --from=certs /etc/ssl/certs/ca-certificates.* /etc/ssl/certs/ 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 [ ] CMD [ "bash" ]