Skip to content
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
918eeab
Make OSS distribution layer reproducible across clean builds
ldziedziul Feb 14, 2026
88a74fc
Use OSS java base image for better reproducibility
ldziedziul Feb 15, 2026
8fa13c8
Make user and package steps reproducible
ldziedziul Feb 15, 2026
53a7a51
Do not install curl - not needed anymore
ldziedziul Feb 15, 2026
fabbc3f
Make EE distribution layer reproducible across clean builds
ldziedziul Feb 16, 2026
b8000b2
Migrate EE to eclipse-temurin base and make all layers reproducible
ldziedziul Feb 16, 2026
728a75f
Switch back to alpine base image to support s390x
ldziedziul Feb 18, 2026
ecb6e3b
Bring back curl for healthcheck
ldziedziul Feb 18, 2026
a64a377
Keep distribution layer separate to limit full rebuilds
ldziedziul Feb 19, 2026
5be04e2
Simplify EE reproducibility
ldziedziul Feb 19, 2026
b9177f0
Add more logging
ldziedziul Feb 19, 2026
4971efd
Remove unnecessary package cleanup
ldziedziul Feb 19, 2026
d6e0f65
Extract upgrading to separate layer
ldziedziul Feb 20, 2026
561f06b
Make line shorter
ldziedziul Feb 20, 2026
5044170
Add ARG to stage
ldziedziul Feb 20, 2026
d440eb1
Add workflow to verify Docker image layer reproducibility
ldziedziul Feb 20, 2026
6dac833
Update .github/workflows/verify-layer-reproducibility.yml
ldziedziul Feb 23, 2026
0d527f4
Update hazelcast-enterprise/Dockerfile
ldziedziul Feb 23, 2026
c88b7db
Update hazelcast-enterprise/Dockerfile
ldziedziul Feb 23, 2026
551173a
Update hazelcast-enterprise/Dockerfile
ldziedziul Feb 23, 2026
4647ec0
Update .github/scripts/verify-layer-reproducibility.sh
ldziedziul Feb 23, 2026
4137118
Update hazelcast-enterprise/Dockerfile
ldziedziul Feb 23, 2026
b9f9f16
Reorder EE layers to align with OS Dockerfile
ldziedziul Feb 23, 2026
45b9319
Extract /build_root to variable
ldziedziul Feb 23, 2026
f8dd562
Extract fake distribution ZIP creation to reusable function
ldziedziul Feb 23, 2026
4f9642e
Add description to SOURCE_DATE_EPOCH
ldziedziul Feb 25, 2026
c2917a6
Describe need of sleep 1
ldziedziul Feb 26, 2026
04736eb
inline readonly
ldziedziul Feb 27, 2026
3ffa221
Refactor script argument handling for verify-layer-reproducibility
ldziedziul Feb 27, 2026
bd779ad
Do not fail-fast when number of layers mismatched
ldziedziul Feb 27, 2026
3297ad1
Remove redundant syntax directive
ldziedziul Feb 27, 2026
35fe78b
Avoid expression duplication
ldziedziul Mar 2, 2026
f1b5010
Fix COPY command in Dockerfile to remove trailing slash
ldziedziul Mar 2, 2026
0ab9ebc
Migrate to rewrite-timestamp=true option
ldziedziul Mar 3, 2026
7f5d06c
Revert EE Dockerfile to ubi9-minimal base image
ldziedziul Mar 4, 2026
7e9e78e
Decouple installing and upgrading in EE to improve reproducibility
ldziedziul Mar 4, 2026
5f4e379
Remove shebang and redundant comment
ldziedziul Mar 4, 2026
a5b5005
Use braces for variables
ldziedziul Mar 4, 2026
c5489d1
Refactor getting digest
ldziedziul Mar 4, 2026
0adde40
Improve variable naming
ldziedziul Mar 5, 2026
5e77e2e
Improve logging
ldziedziul Mar 5, 2026
6d82fdd
Simplify paths
ldziedziul Mar 5, 2026
a71e3a6
Set SOURCE_DATE_EPOCH to 0 and describe it
ldziedziul Mar 5, 2026
1e2615c
Update .github/scripts/verify-layer-reproducibility.sh
ldziedziul Mar 5, 2026
8fe36e8
Update .github/scripts/verify-layer-reproducibility.sh
ldziedziul Mar 5, 2026
a770adc
Fix fake-zip function to work with relative paths
ldziedziul Mar 5, 2026
ad29259
Fix sonar warnings
ldziedziul Mar 5, 2026
01bb1e5
Merge remote-tracking branch 'upstream/master' into reproducible-imag…
ldziedziul Mar 9, 2026
d48e0be
Migrate to hazelcast/docker-actions/verify-docker-reproducibilit action
ldziedziul Mar 9, 2026
bdcee60
Do not exit after preflight check container to see the PREFLIGHT_OUTPUT
ldziedziul Mar 10, 2026
e1a6496
Always print preflight output
ldziedziul Mar 10, 2026
78287a4
Get Image ID of already pushed image
ldziedziul Mar 10, 2026
a3fe046
Fix sonar warning
ldziedziul Mar 11, 2026
f3ed167
Update .github/scripts/rhel.functions.sh
ldziedziul Mar 11, 2026
7b686f6
Update .github/workflows/ee-nlc-tag-package.yml
ldziedziul Mar 12, 2026
a70f24a
Skip RHEL certification when image digest is already published
ldziedziul Mar 12, 2026
2b2aa91
Do not exit after preflight check container to see the PREFLIGHT_OUTPUT
ldziedziul Mar 12, 2026
901b162
Fix digest lookup to use linux/amd64 manifest digest
ldziedziul Mar 12, 2026
24258a9
Improve logging
ldziedziul Mar 12, 2026
3057fe4
Extract amd64 digest from manifest list
ldziedziul Mar 12, 2026
d26cabd
Improve logging
ldziedziul Mar 13, 2026
591b144
Use env variables directly
ldziedziul Mar 13, 2026
1ad8b4e
Skip deleted images in lookup by digest
ldziedziul Mar 13, 2026
5d77c97
Copy tags from DockerHub source to avoid multiple unique tags per image
ldziedziul Mar 13, 2026
20549f0
Extract hardcoded platform into PLATFORM_OS and PLATFORM_ARCH env vars
ldziedziul Mar 16, 2026
314680e
Add comment
ldziedziul Mar 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions .github/scripts/verify-layer-reproducibility.sh

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you considered about writing this in something other than bash?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes but not here ;)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

General comments:

  1. nicely done - although feels little fragile, but then we have a test for this so we are covered. Hopefully it won't break in the future only to be forced to revert back!
  2. is it possible to test in sandbox with a release?
    • what I am after is to see Layer already exists when rebuilding again. In the PR description you have shown that but is that local or via GH? would be good to see links?
  3. presume Dockerfiles have been tested locally (Linux/MacOS)?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. is it possible to test in sandbox with a release?

    • what I am after is to see Layer already exists when rebuilding again. In the PR description you have shown that but is that local or via GH? would be good to see links?

I've run it, but you won't see Layer already exists there as the builds and pushes run in parallel. Nevertheless, when you pull the images you notice layers being reused:

image image
  1. presume Dockerfiles have been tested locally (Linux/MacOS)?

Locally on Macos, and Linux in GH Actions

Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#!/usr/bin/env bash

set -o errexit -o nounset -o pipefail ${RUNNER_DEBUG:+-x}

# Verifies Docker image build reproducibility by building twice and comparing layer digests.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit - standard is to have Usage() ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

something like this
then show usage() if inputs are incorrect - so rather a static comment move it to usage() so can be printed
may be overkill. feel free to skip!

# Exits 0 if all layers are identical across both builds, 1 if any differ.
Comment thread
JackPGreen marked this conversation as resolved.
Outdated
#
# Usage:
# verify-layer-reproducibility.sh -f <dockerfile> [-- <extra buildx build args...>]
#
# Example:
# verify-layer-reproducibility.sh -f hazelcast-oss/Dockerfile -- hazelcast-oss/

RANDOM_SUFFIX="$(head -c 8 /dev/urandom | od -An -tx1 | tr -d ' \n')"
Comment thread
nishaatr marked this conversation as resolved.
Outdated
readonly RANDOM_SUFFIX
readonly TAG_A="repro-check-a-${RANDOM_SUFFIX}"
readonly TAG_B="repro-check-b-${RANDOM_SUFFIX}"

cleanup() {
docker rmi "${TAG_A}" "${TAG_B}" 2>/dev/null || true
}
trap cleanup EXIT

dockerfile=""
while [[ $# -gt 0 ]]; do
Comment thread
nishaatr marked this conversation as resolved.
Outdated
case "$1" in
-f) dockerfile="$2"; shift 2 ;;
--) shift; break ;;
*) echo "Unknown option: $1" >&2; exit 1 ;;
esac
done

if [[ -z "${dockerfile}" ]]; then
Comment thread
nishaatr marked this conversation as resolved.
Outdated
echo "Error: -f <dockerfile> is required" >&2
exit 1
fi

extra_args=("$@")

build_image() {
local tag="$1"
echo "==> Building image '${tag}'..."
docker buildx build \
--no-cache \
--load \
-f "${dockerfile}" \
-t "${tag}" \
"${extra_args[@]}"
}

get_layers() {
docker inspect --format '{{json .RootFS.Layers}}' "$1"
}

build_image "${TAG_A}"
echo ""
build_image "${TAG_B}"
echo ""

layers_a=$(get_layers "${TAG_A}")
layers_b=$(get_layers "${TAG_B}")

count_a=$(echo "${layers_a}" | jq 'length')
count_b=$(echo "${layers_b}" | jq 'length')
Comment thread
ldziedziul marked this conversation as resolved.
Outdated
Comment thread
JackPGreen marked this conversation as resolved.
Outdated

echo "=== Layer Reproducibility Report ==="
echo ""

if [[ "${count_a}" -ne "${count_b}" ]]; then
echo "FAIL: Layer count mismatch (${count_a} vs ${count_b})"
exit 1
Comment thread
nishaatr marked this conversation as resolved.
Outdated
fi

has_diff=false
for i in $(seq 0 $((count_a - 1))); do
digest_a=$(echo "${layers_a}" | jq -r ".[$i]")
digest_b=$(echo "${layers_b}" | jq -r ".[$i]")
if [[ "${digest_a}" == "${digest_b}" ]]; then

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit - could use one liner

diff -y --color -W 40 <(printf "%s\n" "${array1[@]}") <(printf "%s\n" "${array2[@]}") || { echo "Arrays differ!"; exit 1; }

Example output

Image

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not very readable IMHO:

Some layers differ
  sha256:aabbccdd1122334455667788990011223344556677889900aabbccdd11223344   sha256:aabbccdd1122334455667788990011223344556677889900aabbccdd11223344
  sha256:1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef | sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
  sha256:fedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321   sha256:fedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321


Layer count mismatch
  sha256:aabbccdd1122334455667788990011223344556677889900aabbccdd11223344   sha256:aabbccdd1122334455667788990011223344556677889900aabbccdd11223344
  sha256:1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef   sha256:1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef
  sha256:fedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321 <

vs

    Layer 1/3: MATCH
    Layer 2/3: DIFFER
      A: sha256:1234567890abcdef...
      B: sha256:ffffffffffff...
    Layer 3/3: MATCH

echo " Layer $((i + 1))/${count_a}: MATCH"
else
echo " Layer $((i + 1))/${count_a}: DIFFER"
echo " A: ${digest_a}"
echo " B: ${digest_b}"
has_diff=true
fi
done

echo ""
if [[ "${has_diff}" == "true" ]]; then
echo "RESULT: FAIL - some layers differ between builds"
Comment thread
JackPGreen marked this conversation as resolved.
Outdated
exit 1
fi

echo "RESULT: PASS - all ${count_a} layers are identical"
6 changes: 6 additions & 0 deletions .github/workflows/build-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ jobs:
ENVIRONMENT: test
secrets: inherit

verify-reproducibility:
name: Verify layer reproducibility
uses: ./.github/workflows/verify-layer-reproducibility.yml
with:
SOURCE_REF: ${{ github.ref }}

test-push-nlc:
name: Test pushing image
uses: ./.github/workflows/ee-nlc-tag-push.yml
Expand Down
46 changes: 46 additions & 0 deletions .github/workflows/verify-layer-reproducibility.yml
Comment thread
JackPGreen marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Verify layer reproducibility

on:
workflow_call:
inputs:
SOURCE_REF:
description: 'The hazelcast-docker branch to verify'
required: true
type: string
Comment on lines +6 to +9

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to pass this? Isn't it implicit via the github context?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean? SOURCE_REF not needed?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SOURCE_REF allows us to run on one branch (master) using the Dockerfile etc from another branch (e.g. v5.5.9).
But this is only for PR builds - so the SOURCE_REF will always be the ${{ github.ref }} - i.e. PR branch.
So rather than passing it in as a value, we can just skip it and use the implicit/default branch (which will be the PR branch).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for other workflows we pass it, I want to have a unified approach


jobs:
verify:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- context: hazelcast-oss
dist-file: hazelcast-distribution.zip
- context: hazelcast-enterprise
dist-file: hazelcast-enterprise-distribution.zip
steps:
- name: Checkout Code
uses: actions/checkout@v6
with:
ref: ${{ inputs.SOURCE_REF }}

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
Comment thread
JackPGreen marked this conversation as resolved.
Outdated

- name: Create test distribution
run: |
dist_dir=$(mktemp -d)
mkdir -p "$dist_dir/hazelcast-0.0.0/bin" "$dist_dir/hazelcast-0.0.0/lib"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whats the motivation of using temp zip as opposed to HZ snapshot?
Is it smaller/faster?
No issue but thought using HZ zip would be closer to reality and avoid these few lines

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

smaller and faster, we already have similar thing in this repo (which I integrate into a single code)

Comment thread
nishaatr marked this conversation as resolved.
Outdated
printf '#!/bin/bash\n' > "$dist_dir/hazelcast-0.0.0/bin/hz"
printf '#!/bin/bash\n' > "$dist_dir/hazelcast-0.0.0/bin/hz-healthcheck"
chmod +x "$dist_dir/hazelcast-0.0.0/bin/"*
touch "$dist_dir/hazelcast-0.0.0/lib/placeholder"
(cd "$dist_dir" && zip -qr "$GITHUB_WORKSPACE/${{ matrix.context }}/${{ matrix.dist-file }}" hazelcast-0.0.0/)
rm -rf "$dist_dir"
Comment thread
JackPGreen marked this conversation as resolved.
Outdated

- name: Verify layer reproducibility
run: |
.github/scripts/verify-layer-reproducibility.sh \
-f ${{ matrix.context }}/Dockerfile \
-- ${{ matrix.context }}/
64 changes: 38 additions & 26 deletions hazelcast-enterprise/Dockerfile

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In PR description I read this

Image

But don't see this anymore. I think this was before rewrite-timestamp?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# syntax=docker/dockerfile:1.7

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

apparently

:1 as opposed to :1.7 (which points to the latest stable v1 release)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed: 3297ad1

Comment thread
ldziedziul marked this conversation as resolved.
Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this require buildx? Will we run into the same issues as in #1162?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems it requires buildkit

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it seems it requires buildkit

That's annoying, but not unexpected. I think this time around were in a better situation to progress though.

Now we've nailed down that external users extend out images rather than building their own, which means buildx is an exclusively internal requirement - so ensuring our test environments are up to spec can be in scope as part of this.

And we have convincing justification where it adds real customer value, vs last time where it didn't and wasn't worth pushing.


# Used for image metadata only
# Describes the version of the Dockerfile, *not* the version of the bundled Hazelcast binary as this is/can be controlled externally
# Dockerfile needs some concept of versioning so that the release pipeline can tag/archive with an appropriate label
Expand All @@ -8,40 +10,47 @@ ARG HZ_HOME="/opt/hazelcast"
ARG USER_NAME="hazelcast"
ARG USER_GROUP="hazelcast"
ARG JDK_VERSION="21"
ARG SOURCE_DATE_EPOCH=1688223600
Comment thread
JackPGreen marked this conversation as resolved.
Outdated
Comment thread
nishaatr marked this conversation as resolved.
Outdated
Comment thread
JackPGreen marked this conversation as resolved.
Outdated
ARG BUILD_ROOT=/build_root

FROM alpine:3 AS get-distribution

ARG HZ_HOME
ARG SOURCE_DATE_EPOCH
ARG HAZELCAST_ZIP_FILE_NAME="hazelcast-enterprise-distribution.zip"
ARG BUILD_ROOT

# Expects distribution ZIP to be on the local filesystem within the build context
COPY ${HAZELCAST_ZIP_FILE_NAME} /tmp/

RUN mkdir -p ${HZ_HOME} \
RUN mkdir -p ${BUILD_ROOT}${HZ_HOME} \
&& apk add --no-cache unzip \
&& unzip -qq /tmp/${HAZELCAST_ZIP_FILE_NAME} -d /tmp/hz \
# Distribution ZIP structure is a single folder (e.g. "hazelcast-5.4.0-slim") containing the content
# Move all the content up a level so that the path contains no version and is constant
&& mv /tmp/hz/*/* ${HZ_HOME}/ \
&& mv /tmp/hz/*/* ${BUILD_ROOT}${HZ_HOME}/ \
&& apk del unzip \
&& rm -rf /tmp/* \
&& echo "Setting Pardot ID to 'docker'" \
&& echo 'hazelcastDownloadId=docker' > "${HZ_HOME}/lib/hazelcast-download.properties" \
&& echo "Granting read permission to ${HZ_HOME}" \
&& chmod -R +r ${HZ_HOME} \
&& echo 'hazelcastDownloadId=docker' > "${BUILD_ROOT}${HZ_HOME}/lib/hazelcast-download.properties" \
&& echo "Granting read permission to ${BUILD_ROOT}${HZ_HOME}" \
&& chmod -R +r ${BUILD_ROOT}${HZ_HOME} \
&& echo "Grant execute permission to scripts in order to address the issue of permissions not being accurately propagated on Windows OS" \
&& chmod +x ${HZ_HOME}/bin/*
&& chmod +x ${BUILD_ROOT}${HZ_HOME}/bin/*

COPY log4j2.properties log4j2-json.properties jmx_agent_config.yaml ${HZ_HOME}/config/
COPY log4j2.properties log4j2-json.properties jmx_agent_config.yaml ${BUILD_ROOT}${HZ_HOME}/config/

# Normalize timestamps for reproducible layer
RUN find ${BUILD_ROOT} -exec touch -h -d "@$SOURCE_DATE_EPOCH" {} +

FROM redhat/ubi9-minimal:9.7
FROM eclipse-temurin:${JDK_VERSION}-jre-ubi9-minimal

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

slight concern about size.
Can you check pls?
gAI says this:

Image

Seems bigger and has more than what we need like openssl?
Also risk of more packages being added in the future which would increase our image
Probably its ok but though ask!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we used to use JDK java-${JDK_VERSION}-openjdk-headless
why JRE now (which actually makes sense)?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we used to use JDK java-${JDK_VERSION}-openjdk-headless why JRE now (which actually makes sense)?

It was always a JRE (I made the same mistake).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

slight concern about size. Can you check pls? gAI says this:

Image Seems bigger and has more than what we need like `openssl`? Also risk of more packages being added in the future which would increase our image Probably its ok but though ask!

I compared the installed packages in ubi9-minimal + openjdk against the temurin image and there are more differences than I expected.

However - I'm not sure how many of those are because of the different image, or because were changing JDK vendors. E.G. you "need" wget to install Temurin based on their instructions.

Ideally we'd change JDK vendor, then base image seperately to reproducible builds...

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's actually for good spot, there's a lot of differences I haven't expected, especially python presence. I think it could be quite breaking for customers. Taking this into account I've reverted the original base image: 7f5d06c

Comment thread
JackPGreen marked this conversation as resolved.
Outdated
Comment thread
JackPGreen marked this conversation as resolved.
Outdated

ARG HZ_VERSION
ARG HZ_HOME
ARG HZ_VERSION
ARG USER_NAME
ARG USER_GROUP
ARG JDK_VERSION
ARG SOURCE_DATE_EPOCH
ARG BUILD_ROOT

# Runtime variables
ENV HZ_HOME="${HZ_HOME}" \
Expand All @@ -53,7 +62,8 @@ ENV HZ_HOME="${HZ_HOME}" \
JAVA_OPTS="" \
HAZELCAST_CONFIG=config/hazelcast-docker.xml \
LANG=C.UTF-8 \
PATH=${HZ_HOME}/bin:$PATH
PATH=${HZ_HOME}/bin:$PATH \
SOURCE_DATE_EPOCH=${SOURCE_DATE_EPOCH}

LABEL name="Hazelcast Enterprise" \
maintainer="info@hazelcast.com" \
Expand All @@ -67,27 +77,29 @@ LABEL name="Hazelcast Enterprise" \
EXPOSE 5701

COPY licenses /licenses
COPY --from=get-distribution ${HZ_HOME} ${HZ_HOME}/

# Install
RUN echo "Upgrading packages" \
COPY --link --from=get-distribution ${BUILD_ROOT}/ /

RUN touch /tmp/.timestamp-marker && sleep 1 \
&& echo "Adding non-root user" \
&& groupadd --system ${USER_GROUP} \
&& useradd --no-log-init --system --gid ${USER_GROUP} --create-home ${USER_NAME} \
&& chage --lastday 0 ${USER_NAME} \
&& echo "Upgrading packages" \
&& microdnf -y update --nodocs \
&& echo "Installing new packages" \
&& microdnf -y --nodocs --disablerepo=* --enablerepo=ubi-9-appstream-rpms --enablerepo=ubi-9-baseos-rpms \
--disableplugin=subscription-manager install \
java-${JDK_VERSION}-openjdk-headless \
shadow-utils \
tar \
tzdata-java \
util-linux \
&& echo "Removing unnecessary packages and redundant files/folders" \
&& microdnf -y clean all
&& microdnf -y clean all \
&& truncate --size 0 /var/cache/ldconfig/aux-cache \
&& truncate --size 0 /var/lib/dnf/history.sqlite* \
&& echo "Fixing non-deterministic files for reproducibility" \
&& find / -newer /tmp/.timestamp-marker -xdev \
-exec touch -h -d "@$SOURCE_DATE_EPOCH" {} + 2>/dev/null \
&& rm -f /tmp/.timestamp-marker \
&& touch -d "@${SOURCE_DATE_EPOCH}" /tmp


WORKDIR ${HZ_HOME}

RUN echo "Adding non-root user" \
&& groupadd --system ${USER_GROUP} \
&& useradd --no-log-init --system --gid ${USER_GROUP} --create-home ${USER_NAME}
USER ${USER_NAME}

HEALTHCHECK CMD ["hz-healthcheck"]
Expand Down
63 changes: 43 additions & 20 deletions hazelcast-oss/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# syntax=docker/dockerfile:1.7

# Used for image metadata only
# Describes the version of the Dockerfile, *not* the version of the bundled Hazelcast binary as this is/can be controlled externally
# Dockerfile needs some concept of versioning so that the release pipeline can tag/archive with an appropriate label
Expand All @@ -8,39 +10,47 @@ ARG HZ_HOME="/opt/hazelcast"
ARG USER_NAME="hazelcast"
ARG USER_GROUP="hazelcast"
ARG JDK_VERSION="21"
ARG SOURCE_DATE_EPOCH=1688223600
ARG BUILD_ROOT=/build_root

FROM alpine:3 AS get-distribution

ARG HZ_HOME
ARG SOURCE_DATE_EPOCH
ARG HAZELCAST_ZIP_FILE_NAME="hazelcast-distribution.zip"
ARG BUILD_ROOT

# Expects distribution ZIP to be on the local filesystem within the build context
COPY ${HAZELCAST_ZIP_FILE_NAME} /tmp/

RUN mkdir -p ${HZ_HOME} \
RUN mkdir -p ${BUILD_ROOT}${HZ_HOME} \
&& apk add --no-cache unzip \
&& unzip -qq /tmp/${HAZELCAST_ZIP_FILE_NAME} -d /tmp/hz \
# Distribution ZIP structure is a single folder (e.g. "hazelcast-5.4.0-slim") containing the content
# Move all the content up a level so that the path contains no version and is constant
&& mv /tmp/hz/*/* ${HZ_HOME}/ \
&& mv /tmp/hz/*/* ${BUILD_ROOT}${HZ_HOME}/ \
&& apk del unzip \
&& rm -rf /tmp/* \
&& echo "Setting Pardot ID to 'docker'" \
&& echo 'hazelcastDownloadId=docker' > "${HZ_HOME}/lib/hazelcast-download.properties" \
&& echo "Granting read permission to ${HZ_HOME}" \
&& chmod -R +r ${HZ_HOME} \
&& echo 'hazelcastDownloadId=docker' > "${BUILD_ROOT}${HZ_HOME}/lib/hazelcast-download.properties" \
&& echo "Granting read permission to ${BUILD_ROOT}${HZ_HOME}" \
&& chmod -R +r ${BUILD_ROOT}${HZ_HOME} \
&& echo "Grant execute permission to scripts in order to address the issue of permissions not being accurately propagated on Windows OS" \
&& chmod +x ${HZ_HOME}/bin/*
&& chmod +x ${BUILD_ROOT}${HZ_HOME}/bin/*

COPY log4j2.properties log4j2-json.properties jmx_agent_config.yaml ${HZ_HOME}/config/
COPY log4j2.properties log4j2-json.properties jmx_agent_config.yaml ${BUILD_ROOT}${HZ_HOME}/config/

# Normalize timestamps for reproducible layer
RUN find ${BUILD_ROOT} -exec touch -h -d "@$SOURCE_DATE_EPOCH" {} +

FROM alpine:3
Comment thread
nishaatr marked this conversation as resolved.

ARG JDK_VERSION
ARG HZ_HOME
ARG USER_NAME
ARG USER_GROUP
ARG JDK_VERSION
ARG SOURCE_DATE_EPOCH
ARG BUILD_ROOT

# Runtime variables
ENV HZ_HOME="${HZ_HOME}" \
Expand All @@ -52,29 +62,42 @@ ENV HZ_HOME="${HZ_HOME}" \
JAVA_OPTS="" \
HAZELCAST_CONFIG=config/hazelcast-docker.xml \
LANG=C.UTF-8 \
PATH=${HZ_HOME}/bin:$PATH
PATH=${HZ_HOME}/bin:$PATH \
SOURCE_DATE_EPOCH=$SOURCE_DATE_EPOCH

# Expose port
EXPOSE 5701

COPY --from=get-distribution ${HZ_HOME} ${HZ_HOME}/
COPY --link --from=get-distribution ${BUILD_ROOT}/ /

# Install
RUN echo "Upgrading packages" \
&& apk upgrade --no-cache \
RUN touch /tmp/.timestamp-marker && sleep 1 \
Comment thread
ldziedziul marked this conversation as resolved.
Outdated
&& echo "Adding non-root user" \
&& addgroup -S ${USER_GROUP} \
&& adduser -S ${USER_NAME} -G ${USER_GROUP} \
&& echo "Installing new packages" \
&& apk add --no-cache \
&& apk add --no-cache --no-logfile \
openjdk${JDK_VERSION}-jre-headless \
bash \
curl \
openjdk${JDK_VERSION}-jre-headless \
&& echo "Removing unnecessary packages and redundant files/folders" \
&& rm -rf /var/cache/apk/*
&& echo "Regenerating Java cacerts with SOURCE_DATE_EPOCH for reproducibility" \
&& trust extract --overwrite --format=java-cacerts --filter=ca-anchors \
Comment thread
nishaatr marked this conversation as resolved.
Comment thread
nishaatr marked this conversation as resolved.
--purpose server-auth /etc/ssl/certs/java/cacerts \
&& echo "Fixing non-deterministic files for reproducibility" \
&& find / -newer /tmp/.timestamp-marker -xdev \
-exec touch -h -d "@$SOURCE_DATE_EPOCH" {} + 2>/dev/null; \
rm -f /tmp/.timestamp-marker; touch -d "@$SOURCE_DATE_EPOCH" /tmp

# The explicit touch of / /etc /tmp catches parent directories that overlay2 copies up with stale timestamps during
# the upgrade - find -newer misses them because their mtime predates the marker.
RUN touch /tmp/.timestamp-marker && sleep 1 \
&& echo "Upgrading packages" \
&& apk upgrade --no-cache --no-logfile \
&& find / -newer /tmp/.timestamp-marker -xdev \
-exec touch -h -d "@$SOURCE_DATE_EPOCH" {} + 2>/dev/null; \
rm -f /tmp/.timestamp-marker; touch -h -d "@$SOURCE_DATE_EPOCH" / /etc /tmp 2>/dev/null

WORKDIR ${HZ_HOME}

RUN echo "Adding non-root user" \
&& addgroup -S ${USER_GROUP} \
&& adduser -S ${USER_NAME} -G ${USER_GROUP}
USER ${USER_NAME}

HEALTHCHECK CMD ["hz-healthcheck"]
Expand Down
Loading