From f7875e43dd0c8d3daa56710808a538cde275145c Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Thu, 2 May 2024 13:16:14 +0900 Subject: [PATCH] Support reproducible builds (except packages) See docker-library/official-images issue 16044 - `SOURCE_DATE_EPOCH` is added. The value is consumed by the build scripts to make the binary reproducible. - For Debian, `/var/log/*` is removed as they contain timestamps - For Debian, `/var/cache/ldconfig/aux-cache` is removed as they contain inode numbers, etc. - For Alpine, virtual package versions are pinned to "0" to eliminate the timestamp-based version numbers that appear in `/etc/apk/world` and `/lib/apk/db/installed` > [!NOTE] > The following topics are NOT covered by this commit: > > - To reproduce file timestamps in layers, BuildKit has to be executed with > `--output type=,rewrite-timestamp=true`. > Needs BuildKit v0.13 or later. > > - To reproduce the base image by the hash, reproducers may: > - modify the `FROM` instruction in Dockerfile manually > - or, use the `CONVERT` action of source policies to replace the base image. > > > - To reproduce packages, see the `RUN` instruction hook proposed in > moby/buildkit issue 4576 Signed-off-by: Akihiro Suda --- 2.2/Dockerfile | 17 ++++++++++++++++- 2.4/Dockerfile | 17 ++++++++++++++++- 2.4/alpine/Dockerfile | 13 +++++++++++-- 2.6/Dockerfile | 17 ++++++++++++++++- 2.6/alpine/Dockerfile | 13 +++++++++++-- 2.8/Dockerfile | 17 ++++++++++++++++- 2.8/alpine/Dockerfile | 13 +++++++++++-- 2.9/Dockerfile | 17 ++++++++++++++++- 2.9/alpine/Dockerfile | 13 +++++++++++-- 3.0/Dockerfile | 17 ++++++++++++++++- 3.0/alpine/Dockerfile | 13 +++++++++++-- 3.1/Dockerfile | 17 ++++++++++++++++- 3.1/alpine/Dockerfile | 13 +++++++++++-- Dockerfile.template | 26 +++++++++++++++++++++++--- 14 files changed, 201 insertions(+), 22 deletions(-) diff --git a/2.2/Dockerfile b/2.2/Dockerfile index 3854c00..3aaf071 100644 --- a/2.2/Dockerfile +++ b/2.2/Dockerfile @@ -6,6 +6,10 @@ FROM debian:bullseye-slim +# The global SOURCE_DATE_EPOCH is consumed by commands that are not associated with a source artifact. +# This is not propagated from --build-arg: https://github.com/moby/buildkit/issues/4576#issuecomment-2159501282 +ENV SOURCE_DATE_EPOCH 0 + # runtime dependencies RUN set -eux; \ apt-get update; \ @@ -13,9 +17,12 @@ RUN set -eux; \ # @system-ca: https://github.com/docker-library/haproxy/pull/216 ca-certificates \ ; \ - rm -rf /var/lib/apt/lists/* + rm -rf /var/lib/apt/lists/*; \ +# clean up for reproducibility + rm -rf /var/log/* /var/cache/ldconfig/aux-cache # roughly, https://salsa.debian.org/haproxy-team/haproxy/-/blob/732b97ae286906dea19ab5744cf9cf97c364ac1d/debian/haproxy.postinst#L5-6 +# On Debian, useradd recognizes SOURCE_DATE_EPOCH to reproduce the "lastchanged" field in /etc/shadow. RUN set -eux; \ groupadd --gid 99 --system haproxy; \ useradd \ @@ -48,12 +55,18 @@ RUN set -eux; \ zlib1g-dev \ ; \ rm -rf /var/lib/apt/lists/*; \ +# clean up for reproducibility + rm -rf /var/log/* /var/cache/ldconfig/aux-cache ;\ \ wget -O haproxy.tar.gz "$HAPROXY_URL"; \ echo "$HAPROXY_SHA256 *haproxy.tar.gz" | sha256sum -c; \ mkdir -p /usr/src/haproxy; \ tar -xzf haproxy.tar.gz -C /usr/src/haproxy --strip-components=1; \ rm haproxy.tar.gz; \ + SOURCE_DATE_EPOCH="$(find /usr/src/haproxy -type f -exec stat -c '%Y' {} + | sort -nr | head -n1)"; \ + export SOURCE_DATE_EPOCH; \ +# for logging validation/edification + date --date "@$SOURCE_DATE_EPOCH" --rfc-2822; \ \ makeOpts=' \ TARGET=linux-glibc \ @@ -93,6 +106,8 @@ RUN set -eux; \ | xargs -r apt-mark manual \ ; \ apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ +# clean up for reproducibility + rm -rf /var/log/* /var/cache/ldconfig/aux-cache ;\ \ # smoke test haproxy -v diff --git a/2.4/Dockerfile b/2.4/Dockerfile index fcc5bfe..e00b2e0 100644 --- a/2.4/Dockerfile +++ b/2.4/Dockerfile @@ -6,6 +6,10 @@ FROM debian:bookworm-slim +# The global SOURCE_DATE_EPOCH is consumed by commands that are not associated with a source artifact. +# This is not propagated from --build-arg: https://github.com/moby/buildkit/issues/4576#issuecomment-2159501282 +ENV SOURCE_DATE_EPOCH 0 + # runtime dependencies RUN set -eux; \ apt-get update; \ @@ -13,9 +17,12 @@ RUN set -eux; \ # @system-ca: https://github.com/docker-library/haproxy/pull/216 ca-certificates \ ; \ - rm -rf /var/lib/apt/lists/* + rm -rf /var/lib/apt/lists/*; \ +# clean up for reproducibility + rm -rf /var/log/* /var/cache/ldconfig/aux-cache # roughly, https://salsa.debian.org/haproxy-team/haproxy/-/blob/732b97ae286906dea19ab5744cf9cf97c364ac1d/debian/haproxy.postinst#L5-6 +# On Debian, useradd recognizes SOURCE_DATE_EPOCH to reproduce the "lastchanged" field in /etc/shadow. RUN set -eux; \ groupadd --gid 99 --system haproxy; \ useradd \ @@ -47,12 +54,18 @@ RUN set -eux; \ wget \ ; \ rm -rf /var/lib/apt/lists/*; \ +# clean up for reproducibility + rm -rf /var/log/* /var/cache/ldconfig/aux-cache ;\ \ wget -O haproxy.tar.gz "$HAPROXY_URL"; \ echo "$HAPROXY_SHA256 *haproxy.tar.gz" | sha256sum -c; \ mkdir -p /usr/src/haproxy; \ tar -xzf haproxy.tar.gz -C /usr/src/haproxy --strip-components=1; \ rm haproxy.tar.gz; \ + SOURCE_DATE_EPOCH="$(find /usr/src/haproxy -type f -exec stat -c '%Y' {} + | sort -nr | head -n1)"; \ + export SOURCE_DATE_EPOCH; \ +# for logging validation/edification + date --date "@$SOURCE_DATE_EPOCH" --rfc-2822; \ \ makeOpts=' \ TARGET=linux-glibc \ @@ -90,6 +103,8 @@ RUN set -eux; \ | xargs -r apt-mark manual \ ; \ apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ +# clean up for reproducibility + rm -rf /var/log/* /var/cache/ldconfig/aux-cache ;\ \ # smoke test haproxy -v diff --git a/2.4/alpine/Dockerfile b/2.4/alpine/Dockerfile index db97f30..da86816 100644 --- a/2.4/alpine/Dockerfile +++ b/2.4/alpine/Dockerfile @@ -6,6 +6,10 @@ FROM alpine:3.20 +# The global SOURCE_DATE_EPOCH is consumed by commands that are not associated with a source artifact. +# This is not propagated from --build-arg: https://github.com/moby/buildkit/issues/4576#issuecomment-2159501282 +ENV SOURCE_DATE_EPOCH 0 + # runtime dependencies RUN set -eux; \ apk add --no-cache \ @@ -14,6 +18,7 @@ RUN set -eux; \ ; # roughly, https://git.alpinelinux.org/aports/tree/main/haproxy/haproxy.pre-install?h=3.12-stable +# On Alpine, useradd still does not recognize SOURCE_DATE_EPOCH to reproduce the "lastchanged" field in /etc/shadow. RUN set -eux; \ addgroup --gid 99 --system haproxy; \ adduser \ @@ -35,7 +40,7 @@ ENV HAPROXY_SHA256 61ec3221942c3fd379aa0cecf65c28c3af3e5513535eed73beda99ca89ad0 # see https://sources.debian.net/src/haproxy/jessie/debian/rules/ for some helpful navigation of the possible "make" arguments RUN set -eux; \ \ - apk add --no-cache --virtual .build-deps \ + apk add --no-cache --virtual .build-deps=0 \ gcc \ libc-dev \ linux-headers \ @@ -53,6 +58,10 @@ RUN set -eux; \ mkdir -p /usr/src/haproxy; \ tar -xzf haproxy.tar.gz -C /usr/src/haproxy --strip-components=1; \ rm haproxy.tar.gz; \ + SOURCE_DATE_EPOCH="$(find /usr/src/haproxy -type f -exec stat -c '%Y' {} + | sort -nr | head -n1)"; \ + export SOURCE_DATE_EPOCH; \ +# for logging validation/edification + date --date "@$SOURCE_DATE_EPOCH" --rfc-2822; \ \ makeOpts=' \ TARGET=linux-musl \ @@ -80,7 +89,7 @@ RUN set -eux; \ | sort -u \ | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ )"; \ - apk add --no-network --virtual .haproxy-rundeps $runDeps; \ + apk add --no-network --virtual .haproxy-rundeps=0 $runDeps; \ apk del --no-network .build-deps; \ \ # smoke test diff --git a/2.6/Dockerfile b/2.6/Dockerfile index 269a997..905555e 100644 --- a/2.6/Dockerfile +++ b/2.6/Dockerfile @@ -6,6 +6,10 @@ FROM debian:bookworm-slim +# The global SOURCE_DATE_EPOCH is consumed by commands that are not associated with a source artifact. +# This is not propagated from --build-arg: https://github.com/moby/buildkit/issues/4576#issuecomment-2159501282 +ENV SOURCE_DATE_EPOCH 0 + # runtime dependencies RUN set -eux; \ apt-get update; \ @@ -13,9 +17,12 @@ RUN set -eux; \ # @system-ca: https://github.com/docker-library/haproxy/pull/216 ca-certificates \ ; \ - rm -rf /var/lib/apt/lists/* + rm -rf /var/lib/apt/lists/*; \ +# clean up for reproducibility + rm -rf /var/log/* /var/cache/ldconfig/aux-cache # roughly, https://salsa.debian.org/haproxy-team/haproxy/-/blob/732b97ae286906dea19ab5744cf9cf97c364ac1d/debian/haproxy.postinst#L5-6 +# On Debian, useradd recognizes SOURCE_DATE_EPOCH to reproduce the "lastchanged" field in /etc/shadow. RUN set -eux; \ groupadd --gid 99 --system haproxy; \ useradd \ @@ -47,12 +54,18 @@ RUN set -eux; \ wget \ ; \ rm -rf /var/lib/apt/lists/*; \ +# clean up for reproducibility + rm -rf /var/log/* /var/cache/ldconfig/aux-cache ;\ \ wget -O haproxy.tar.gz "$HAPROXY_URL"; \ echo "$HAPROXY_SHA256 *haproxy.tar.gz" | sha256sum -c; \ mkdir -p /usr/src/haproxy; \ tar -xzf haproxy.tar.gz -C /usr/src/haproxy --strip-components=1; \ rm haproxy.tar.gz; \ + SOURCE_DATE_EPOCH="$(find /usr/src/haproxy -type f -exec stat -c '%Y' {} + | sort -nr | head -n1)"; \ + export SOURCE_DATE_EPOCH; \ +# for logging validation/edification + date --date "@$SOURCE_DATE_EPOCH" --rfc-2822; \ \ makeOpts=' \ TARGET=linux-glibc \ @@ -90,6 +103,8 @@ RUN set -eux; \ | xargs -r apt-mark manual \ ; \ apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ +# clean up for reproducibility + rm -rf /var/log/* /var/cache/ldconfig/aux-cache ;\ \ # smoke test haproxy -v diff --git a/2.6/alpine/Dockerfile b/2.6/alpine/Dockerfile index 6d1206e..1baaccb 100644 --- a/2.6/alpine/Dockerfile +++ b/2.6/alpine/Dockerfile @@ -6,6 +6,10 @@ FROM alpine:3.20 +# The global SOURCE_DATE_EPOCH is consumed by commands that are not associated with a source artifact. +# This is not propagated from --build-arg: https://github.com/moby/buildkit/issues/4576#issuecomment-2159501282 +ENV SOURCE_DATE_EPOCH 0 + # runtime dependencies RUN set -eux; \ apk add --no-cache \ @@ -14,6 +18,7 @@ RUN set -eux; \ ; # roughly, https://git.alpinelinux.org/aports/tree/main/haproxy/haproxy.pre-install?h=3.12-stable +# On Alpine, useradd still does not recognize SOURCE_DATE_EPOCH to reproduce the "lastchanged" field in /etc/shadow. RUN set -eux; \ addgroup --gid 99 --system haproxy; \ adduser \ @@ -35,7 +40,7 @@ ENV HAPROXY_SHA256 890a2fdd12e92115556b5d2ff578c1f9a8e48147ea5fe9efb8145685f723a # see https://sources.debian.net/src/haproxy/jessie/debian/rules/ for some helpful navigation of the possible "make" arguments RUN set -eux; \ \ - apk add --no-cache --virtual .build-deps \ + apk add --no-cache --virtual .build-deps=0 \ gcc \ libc-dev \ linux-headers \ @@ -53,6 +58,10 @@ RUN set -eux; \ mkdir -p /usr/src/haproxy; \ tar -xzf haproxy.tar.gz -C /usr/src/haproxy --strip-components=1; \ rm haproxy.tar.gz; \ + SOURCE_DATE_EPOCH="$(find /usr/src/haproxy -type f -exec stat -c '%Y' {} + | sort -nr | head -n1)"; \ + export SOURCE_DATE_EPOCH; \ +# for logging validation/edification + date --date "@$SOURCE_DATE_EPOCH" --rfc-2822; \ \ makeOpts=' \ TARGET=linux-musl \ @@ -80,7 +89,7 @@ RUN set -eux; \ | sort -u \ | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ )"; \ - apk add --no-network --virtual .haproxy-rundeps $runDeps; \ + apk add --no-network --virtual .haproxy-rundeps=0 $runDeps; \ apk del --no-network .build-deps; \ \ # smoke test diff --git a/2.8/Dockerfile b/2.8/Dockerfile index cf2fc8c..657d66a 100644 --- a/2.8/Dockerfile +++ b/2.8/Dockerfile @@ -6,6 +6,10 @@ FROM debian:bookworm-slim +# The global SOURCE_DATE_EPOCH is consumed by commands that are not associated with a source artifact. +# This is not propagated from --build-arg: https://github.com/moby/buildkit/issues/4576#issuecomment-2159501282 +ENV SOURCE_DATE_EPOCH 0 + # runtime dependencies RUN set -eux; \ apt-get update; \ @@ -13,9 +17,12 @@ RUN set -eux; \ # @system-ca: https://github.com/docker-library/haproxy/pull/216 ca-certificates \ ; \ - rm -rf /var/lib/apt/lists/* + rm -rf /var/lib/apt/lists/*; \ +# clean up for reproducibility + rm -rf /var/log/* /var/cache/ldconfig/aux-cache # roughly, https://salsa.debian.org/haproxy-team/haproxy/-/blob/732b97ae286906dea19ab5744cf9cf97c364ac1d/debian/haproxy.postinst#L5-6 +# On Debian, useradd recognizes SOURCE_DATE_EPOCH to reproduce the "lastchanged" field in /etc/shadow. RUN set -eux; \ groupadd --gid 99 --system haproxy; \ useradd \ @@ -47,12 +54,18 @@ RUN set -eux; \ wget \ ; \ rm -rf /var/lib/apt/lists/*; \ +# clean up for reproducibility + rm -rf /var/log/* /var/cache/ldconfig/aux-cache ;\ \ wget -O haproxy.tar.gz "$HAPROXY_URL"; \ echo "$HAPROXY_SHA256 *haproxy.tar.gz" | sha256sum -c; \ mkdir -p /usr/src/haproxy; \ tar -xzf haproxy.tar.gz -C /usr/src/haproxy --strip-components=1; \ rm haproxy.tar.gz; \ + SOURCE_DATE_EPOCH="$(find /usr/src/haproxy -type f -exec stat -c '%Y' {} + | sort -nr | head -n1)"; \ + export SOURCE_DATE_EPOCH; \ +# for logging validation/edification + date --date "@$SOURCE_DATE_EPOCH" --rfc-2822; \ \ makeOpts=' \ TARGET=linux-glibc \ @@ -90,6 +103,8 @@ RUN set -eux; \ | xargs -r apt-mark manual \ ; \ apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ +# clean up for reproducibility + rm -rf /var/log/* /var/cache/ldconfig/aux-cache ;\ \ # smoke test haproxy -v diff --git a/2.8/alpine/Dockerfile b/2.8/alpine/Dockerfile index 41b924f..cf0d1fa 100644 --- a/2.8/alpine/Dockerfile +++ b/2.8/alpine/Dockerfile @@ -6,6 +6,10 @@ FROM alpine:3.20 +# The global SOURCE_DATE_EPOCH is consumed by commands that are not associated with a source artifact. +# This is not propagated from --build-arg: https://github.com/moby/buildkit/issues/4576#issuecomment-2159501282 +ENV SOURCE_DATE_EPOCH 0 + # runtime dependencies RUN set -eux; \ apk add --no-cache \ @@ -14,6 +18,7 @@ RUN set -eux; \ ; # roughly, https://git.alpinelinux.org/aports/tree/main/haproxy/haproxy.pre-install?h=3.12-stable +# On Alpine, useradd still does not recognize SOURCE_DATE_EPOCH to reproduce the "lastchanged" field in /etc/shadow. RUN set -eux; \ addgroup --gid 99 --system haproxy; \ adduser \ @@ -35,7 +40,7 @@ ENV HAPROXY_SHA256 39de529ae0283416acb5477197ece17ea05b81f467bec5a6ac73cbad7dd53 # see https://sources.debian.net/src/haproxy/jessie/debian/rules/ for some helpful navigation of the possible "make" arguments RUN set -eux; \ \ - apk add --no-cache --virtual .build-deps \ + apk add --no-cache --virtual .build-deps=0 \ gcc \ libc-dev \ linux-headers \ @@ -53,6 +58,10 @@ RUN set -eux; \ mkdir -p /usr/src/haproxy; \ tar -xzf haproxy.tar.gz -C /usr/src/haproxy --strip-components=1; \ rm haproxy.tar.gz; \ + SOURCE_DATE_EPOCH="$(find /usr/src/haproxy -type f -exec stat -c '%Y' {} + | sort -nr | head -n1)"; \ + export SOURCE_DATE_EPOCH; \ +# for logging validation/edification + date --date "@$SOURCE_DATE_EPOCH" --rfc-2822; \ \ makeOpts=' \ TARGET=linux-musl \ @@ -80,7 +89,7 @@ RUN set -eux; \ | sort -u \ | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ )"; \ - apk add --no-network --virtual .haproxy-rundeps $runDeps; \ + apk add --no-network --virtual .haproxy-rundeps=0 $runDeps; \ apk del --no-network .build-deps; \ \ # smoke test diff --git a/2.9/Dockerfile b/2.9/Dockerfile index d1fc8f7..d8c6f23 100644 --- a/2.9/Dockerfile +++ b/2.9/Dockerfile @@ -6,6 +6,10 @@ FROM debian:bookworm-slim +# The global SOURCE_DATE_EPOCH is consumed by commands that are not associated with a source artifact. +# This is not propagated from --build-arg: https://github.com/moby/buildkit/issues/4576#issuecomment-2159501282 +ENV SOURCE_DATE_EPOCH 0 + # runtime dependencies RUN set -eux; \ apt-get update; \ @@ -13,9 +17,12 @@ RUN set -eux; \ # @system-ca: https://github.com/docker-library/haproxy/pull/216 ca-certificates \ ; \ - rm -rf /var/lib/apt/lists/* + rm -rf /var/lib/apt/lists/*; \ +# clean up for reproducibility + rm -rf /var/log/* /var/cache/ldconfig/aux-cache # roughly, https://salsa.debian.org/haproxy-team/haproxy/-/blob/732b97ae286906dea19ab5744cf9cf97c364ac1d/debian/haproxy.postinst#L5-6 +# On Debian, useradd recognizes SOURCE_DATE_EPOCH to reproduce the "lastchanged" field in /etc/shadow. RUN set -eux; \ groupadd --gid 99 --system haproxy; \ useradd \ @@ -47,12 +54,18 @@ RUN set -eux; \ wget \ ; \ rm -rf /var/lib/apt/lists/*; \ +# clean up for reproducibility + rm -rf /var/log/* /var/cache/ldconfig/aux-cache ;\ \ wget -O haproxy.tar.gz "$HAPROXY_URL"; \ echo "$HAPROXY_SHA256 *haproxy.tar.gz" | sha256sum -c; \ mkdir -p /usr/src/haproxy; \ tar -xzf haproxy.tar.gz -C /usr/src/haproxy --strip-components=1; \ rm haproxy.tar.gz; \ + SOURCE_DATE_EPOCH="$(find /usr/src/haproxy -type f -exec stat -c '%Y' {} + | sort -nr | head -n1)"; \ + export SOURCE_DATE_EPOCH; \ +# for logging validation/edification + date --date "@$SOURCE_DATE_EPOCH" --rfc-2822; \ \ makeOpts=' \ TARGET=linux-glibc \ @@ -90,6 +103,8 @@ RUN set -eux; \ | xargs -r apt-mark manual \ ; \ apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ +# clean up for reproducibility + rm -rf /var/log/* /var/cache/ldconfig/aux-cache ;\ \ # smoke test haproxy -v diff --git a/2.9/alpine/Dockerfile b/2.9/alpine/Dockerfile index 257de4f..ba3335f 100644 --- a/2.9/alpine/Dockerfile +++ b/2.9/alpine/Dockerfile @@ -6,6 +6,10 @@ FROM alpine:3.20 +# The global SOURCE_DATE_EPOCH is consumed by commands that are not associated with a source artifact. +# This is not propagated from --build-arg: https://github.com/moby/buildkit/issues/4576#issuecomment-2159501282 +ENV SOURCE_DATE_EPOCH 0 + # runtime dependencies RUN set -eux; \ apk add --no-cache \ @@ -14,6 +18,7 @@ RUN set -eux; \ ; # roughly, https://git.alpinelinux.org/aports/tree/main/haproxy/haproxy.pre-install?h=3.12-stable +# On Alpine, useradd still does not recognize SOURCE_DATE_EPOCH to reproduce the "lastchanged" field in /etc/shadow. RUN set -eux; \ addgroup --gid 99 --system haproxy; \ adduser \ @@ -35,7 +40,7 @@ ENV HAPROXY_SHA256 2375281ddf81e201b531d4119c686356d1d37d0afc4bc0e3b6dcec9f2e556 # see https://sources.debian.net/src/haproxy/jessie/debian/rules/ for some helpful navigation of the possible "make" arguments RUN set -eux; \ \ - apk add --no-cache --virtual .build-deps \ + apk add --no-cache --virtual .build-deps=0 \ gcc \ libc-dev \ linux-headers \ @@ -53,6 +58,10 @@ RUN set -eux; \ mkdir -p /usr/src/haproxy; \ tar -xzf haproxy.tar.gz -C /usr/src/haproxy --strip-components=1; \ rm haproxy.tar.gz; \ + SOURCE_DATE_EPOCH="$(find /usr/src/haproxy -type f -exec stat -c '%Y' {} + | sort -nr | head -n1)"; \ + export SOURCE_DATE_EPOCH; \ +# for logging validation/edification + date --date "@$SOURCE_DATE_EPOCH" --rfc-2822; \ \ makeOpts=' \ TARGET=linux-musl \ @@ -80,7 +89,7 @@ RUN set -eux; \ | sort -u \ | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ )"; \ - apk add --no-network --virtual .haproxy-rundeps $runDeps; \ + apk add --no-network --virtual .haproxy-rundeps=0 $runDeps; \ apk del --no-network .build-deps; \ \ # smoke test diff --git a/3.0/Dockerfile b/3.0/Dockerfile index 99f39d0..bb3e023 100644 --- a/3.0/Dockerfile +++ b/3.0/Dockerfile @@ -6,6 +6,10 @@ FROM debian:bookworm-slim +# The global SOURCE_DATE_EPOCH is consumed by commands that are not associated with a source artifact. +# This is not propagated from --build-arg: https://github.com/moby/buildkit/issues/4576#issuecomment-2159501282 +ENV SOURCE_DATE_EPOCH 0 + # runtime dependencies RUN set -eux; \ apt-get update; \ @@ -13,9 +17,12 @@ RUN set -eux; \ # @system-ca: https://github.com/docker-library/haproxy/pull/216 ca-certificates \ ; \ - rm -rf /var/lib/apt/lists/* + rm -rf /var/lib/apt/lists/*; \ +# clean up for reproducibility + rm -rf /var/log/* /var/cache/ldconfig/aux-cache # roughly, https://salsa.debian.org/haproxy-team/haproxy/-/blob/732b97ae286906dea19ab5744cf9cf97c364ac1d/debian/haproxy.postinst#L5-6 +# On Debian, useradd recognizes SOURCE_DATE_EPOCH to reproduce the "lastchanged" field in /etc/shadow. RUN set -eux; \ groupadd --gid 99 --system haproxy; \ useradd \ @@ -47,12 +54,18 @@ RUN set -eux; \ wget \ ; \ rm -rf /var/lib/apt/lists/*; \ +# clean up for reproducibility + rm -rf /var/log/* /var/cache/ldconfig/aux-cache ;\ \ wget -O haproxy.tar.gz "$HAPROXY_URL"; \ echo "$HAPROXY_SHA256 *haproxy.tar.gz" | sha256sum -c; \ mkdir -p /usr/src/haproxy; \ tar -xzf haproxy.tar.gz -C /usr/src/haproxy --strip-components=1; \ rm haproxy.tar.gz; \ + SOURCE_DATE_EPOCH="$(find /usr/src/haproxy -type f -exec stat -c '%Y' {} + | sort -nr | head -n1)"; \ + export SOURCE_DATE_EPOCH; \ +# for logging validation/edification + date --date "@$SOURCE_DATE_EPOCH" --rfc-2822; \ \ makeOpts=' \ TARGET=linux-glibc \ @@ -90,6 +103,8 @@ RUN set -eux; \ | xargs -r apt-mark manual \ ; \ apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ +# clean up for reproducibility + rm -rf /var/log/* /var/cache/ldconfig/aux-cache ;\ \ # smoke test haproxy -v diff --git a/3.0/alpine/Dockerfile b/3.0/alpine/Dockerfile index 214f1cc..449c235 100644 --- a/3.0/alpine/Dockerfile +++ b/3.0/alpine/Dockerfile @@ -6,6 +6,10 @@ FROM alpine:3.20 +# The global SOURCE_DATE_EPOCH is consumed by commands that are not associated with a source artifact. +# This is not propagated from --build-arg: https://github.com/moby/buildkit/issues/4576#issuecomment-2159501282 +ENV SOURCE_DATE_EPOCH 0 + # runtime dependencies RUN set -eux; \ apk add --no-cache \ @@ -14,6 +18,7 @@ RUN set -eux; \ ; # roughly, https://git.alpinelinux.org/aports/tree/main/haproxy/haproxy.pre-install?h=3.12-stable +# On Alpine, useradd still does not recognize SOURCE_DATE_EPOCH to reproduce the "lastchanged" field in /etc/shadow. RUN set -eux; \ addgroup --gid 99 --system haproxy; \ adduser \ @@ -35,7 +40,7 @@ ENV HAPROXY_SHA256 ae38221e85aeba038a725efbef5bfe5e76671ba7959e5eb74c39fd079e5d0 # see https://sources.debian.net/src/haproxy/jessie/debian/rules/ for some helpful navigation of the possible "make" arguments RUN set -eux; \ \ - apk add --no-cache --virtual .build-deps \ + apk add --no-cache --virtual .build-deps=0 \ gcc \ libc-dev \ linux-headers \ @@ -53,6 +58,10 @@ RUN set -eux; \ mkdir -p /usr/src/haproxy; \ tar -xzf haproxy.tar.gz -C /usr/src/haproxy --strip-components=1; \ rm haproxy.tar.gz; \ + SOURCE_DATE_EPOCH="$(find /usr/src/haproxy -type f -exec stat -c '%Y' {} + | sort -nr | head -n1)"; \ + export SOURCE_DATE_EPOCH; \ +# for logging validation/edification + date --date "@$SOURCE_DATE_EPOCH" --rfc-2822; \ \ makeOpts=' \ TARGET=linux-musl \ @@ -80,7 +89,7 @@ RUN set -eux; \ | sort -u \ | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ )"; \ - apk add --no-network --virtual .haproxy-rundeps $runDeps; \ + apk add --no-network --virtual .haproxy-rundeps=0 $runDeps; \ apk del --no-network .build-deps; \ \ # smoke test diff --git a/3.1/Dockerfile b/3.1/Dockerfile index ca4f316..2e9fe9d 100644 --- a/3.1/Dockerfile +++ b/3.1/Dockerfile @@ -6,6 +6,10 @@ FROM debian:bookworm-slim +# The global SOURCE_DATE_EPOCH is consumed by commands that are not associated with a source artifact. +# This is not propagated from --build-arg: https://github.com/moby/buildkit/issues/4576#issuecomment-2159501282 +ENV SOURCE_DATE_EPOCH 0 + # runtime dependencies RUN set -eux; \ apt-get update; \ @@ -13,9 +17,12 @@ RUN set -eux; \ # @system-ca: https://github.com/docker-library/haproxy/pull/216 ca-certificates \ ; \ - rm -rf /var/lib/apt/lists/* + rm -rf /var/lib/apt/lists/*; \ +# clean up for reproducibility + rm -rf /var/log/* /var/cache/ldconfig/aux-cache # roughly, https://salsa.debian.org/haproxy-team/haproxy/-/blob/732b97ae286906dea19ab5744cf9cf97c364ac1d/debian/haproxy.postinst#L5-6 +# On Debian, useradd recognizes SOURCE_DATE_EPOCH to reproduce the "lastchanged" field in /etc/shadow. RUN set -eux; \ groupadd --gid 99 --system haproxy; \ useradd \ @@ -47,12 +54,18 @@ RUN set -eux; \ wget \ ; \ rm -rf /var/lib/apt/lists/*; \ +# clean up for reproducibility + rm -rf /var/log/* /var/cache/ldconfig/aux-cache ;\ \ wget -O haproxy.tar.gz "$HAPROXY_URL"; \ echo "$HAPROXY_SHA256 *haproxy.tar.gz" | sha256sum -c; \ mkdir -p /usr/src/haproxy; \ tar -xzf haproxy.tar.gz -C /usr/src/haproxy --strip-components=1; \ rm haproxy.tar.gz; \ + SOURCE_DATE_EPOCH="$(find /usr/src/haproxy -type f -exec stat -c '%Y' {} + | sort -nr | head -n1)"; \ + export SOURCE_DATE_EPOCH; \ +# for logging validation/edification + date --date "@$SOURCE_DATE_EPOCH" --rfc-2822; \ \ makeOpts=' \ TARGET=linux-glibc \ @@ -90,6 +103,8 @@ RUN set -eux; \ | xargs -r apt-mark manual \ ; \ apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ +# clean up for reproducibility + rm -rf /var/log/* /var/cache/ldconfig/aux-cache ;\ \ # smoke test haproxy -v diff --git a/3.1/alpine/Dockerfile b/3.1/alpine/Dockerfile index 48e5adb..9ff3c87 100644 --- a/3.1/alpine/Dockerfile +++ b/3.1/alpine/Dockerfile @@ -6,6 +6,10 @@ FROM alpine:3.20 +# The global SOURCE_DATE_EPOCH is consumed by commands that are not associated with a source artifact. +# This is not propagated from --build-arg: https://github.com/moby/buildkit/issues/4576#issuecomment-2159501282 +ENV SOURCE_DATE_EPOCH 0 + # runtime dependencies RUN set -eux; \ apk add --no-cache \ @@ -14,6 +18,7 @@ RUN set -eux; \ ; # roughly, https://git.alpinelinux.org/aports/tree/main/haproxy/haproxy.pre-install?h=3.12-stable +# On Alpine, useradd still does not recognize SOURCE_DATE_EPOCH to reproduce the "lastchanged" field in /etc/shadow. RUN set -eux; \ addgroup --gid 99 --system haproxy; \ adduser \ @@ -35,7 +40,7 @@ ENV HAPROXY_SHA256 185b85db5092bc6dfbc4ab2e221c867caef5479bb623cc25f9d3c865b8d0b # see https://sources.debian.net/src/haproxy/jessie/debian/rules/ for some helpful navigation of the possible "make" arguments RUN set -eux; \ \ - apk add --no-cache --virtual .build-deps \ + apk add --no-cache --virtual .build-deps=0 \ gcc \ libc-dev \ linux-headers \ @@ -53,6 +58,10 @@ RUN set -eux; \ mkdir -p /usr/src/haproxy; \ tar -xzf haproxy.tar.gz -C /usr/src/haproxy --strip-components=1; \ rm haproxy.tar.gz; \ + SOURCE_DATE_EPOCH="$(find /usr/src/haproxy -type f -exec stat -c '%Y' {} + | sort -nr | head -n1)"; \ + export SOURCE_DATE_EPOCH; \ +# for logging validation/edification + date --date "@$SOURCE_DATE_EPOCH" --rfc-2822; \ \ makeOpts=' \ TARGET=linux-musl \ @@ -80,7 +89,7 @@ RUN set -eux; \ | sort -u \ | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ )"; \ - apk add --no-network --virtual .haproxy-rundeps $runDeps; \ + apk add --no-network --virtual .haproxy-rundeps=0 $runDeps; \ apk del --no-network .build-deps; \ \ # smoke test diff --git a/Dockerfile.template b/Dockerfile.template index 05d1f8a..b6f87c3 100644 --- a/Dockerfile.template +++ b/Dockerfile.template @@ -1,6 +1,10 @@ {{ if env.variant == "alpine" then ( -}} FROM alpine:{{ .alpine }} +# The global SOURCE_DATE_EPOCH is consumed by commands that are not associated with a source artifact. +# This is not propagated from --build-arg: https://github.com/moby/buildkit/issues/4576#issuecomment-2159501282 +ENV SOURCE_DATE_EPOCH 0 + # runtime dependencies RUN set -eux; \ apk add --no-cache \ @@ -9,6 +13,7 @@ RUN set -eux; \ ; # roughly, https://git.alpinelinux.org/aports/tree/main/haproxy/haproxy.pre-install?h=3.12-stable +# On Alpine, useradd still does not recognize SOURCE_DATE_EPOCH to reproduce the "lastchanged" field in /etc/shadow. RUN set -eux; \ addgroup --gid 99 --system haproxy; \ adduser \ @@ -25,6 +30,10 @@ RUN set -eux; \ {{ ) else ( -}} FROM debian:{{ .debian }} +# The global SOURCE_DATE_EPOCH is consumed by commands that are not associated with a source artifact. +# This is not propagated from --build-arg: https://github.com/moby/buildkit/issues/4576#issuecomment-2159501282 +ENV SOURCE_DATE_EPOCH 0 + # runtime dependencies RUN set -eux; \ apt-get update; \ @@ -32,9 +41,12 @@ RUN set -eux; \ # @system-ca: https://github.com/docker-library/haproxy/pull/216 ca-certificates \ ; \ - rm -rf /var/lib/apt/lists/* + rm -rf /var/lib/apt/lists/*; \ +# clean up for reproducibility + rm -rf /var/log/* /var/cache/ldconfig/aux-cache # roughly, https://salsa.debian.org/haproxy-team/haproxy/-/blob/732b97ae286906dea19ab5744cf9cf97c364ac1d/debian/haproxy.postinst#L5-6 +# On Debian, useradd recognizes SOURCE_DATE_EPOCH to reproduce the "lastchanged" field in /etc/shadow. RUN set -eux; \ groupadd --gid 99 --system haproxy; \ useradd \ @@ -70,7 +82,7 @@ ENV HAPROXY_SHA256 {{ .sha256 }} RUN set -eux; \ \ {{ if env.variant == "alpine" then ( -}} - apk add --no-cache --virtual .build-deps \ + apk add --no-cache --virtual .build-deps=0 \ gcc \ libc-dev \ linux-headers \ @@ -100,6 +112,8 @@ RUN set -eux; \ {{ ) else "" end -}} ; \ rm -rf /var/lib/apt/lists/*; \ +# clean up for reproducibility + rm -rf /var/log/* /var/cache/ldconfig/aux-cache ;\ {{ ) end -}} \ wget -O haproxy.tar.gz "$HAPROXY_URL"; \ @@ -107,6 +121,10 @@ RUN set -eux; \ mkdir -p /usr/src/haproxy; \ tar -xzf haproxy.tar.gz -C /usr/src/haproxy --strip-components=1; \ rm haproxy.tar.gz; \ + SOURCE_DATE_EPOCH="$(find /usr/src/haproxy -type f -exec stat -c '%Y' {} + | sort -nr | head -n1)"; \ + export SOURCE_DATE_EPOCH; \ +# for logging validation/edification + date --date "@$SOURCE_DATE_EPOCH" --rfc-2822; \ \ {{ def haproxy_target: @@ -162,7 +180,7 @@ RUN set -eux; \ | sort -u \ | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \ )"; \ - apk add --no-network --virtual .haproxy-rundeps $runDeps; \ + apk add --no-network --virtual .haproxy-rundeps=0 $runDeps; \ apk del --no-network .build-deps; \ {{ ) else ( -}} apt-mark auto '.*' > /dev/null; \ @@ -176,6 +194,8 @@ RUN set -eux; \ | xargs -r apt-mark manual \ ; \ apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \ +# clean up for reproducibility + rm -rf /var/log/* /var/cache/ldconfig/aux-cache ;\ {{ ) end -}} \ # smoke test