fix(docker): stop a stale VERSION_TAG env var masking the image version

This commit is contained in:
Anthony Stirling
2026-08-21 08:14:52 +01:00
parent e092b487ec
commit eb1435807d
7 changed files with 107 additions and 12 deletions
+1 -2
View File
@@ -89,12 +89,11 @@ RUN set -eux; \
RUN echo "${VERSION_TAG:-dev}" > /etc/stirling_version
# Environment variables
ENV VERSION_TAG=$VERSION_TAG \
ENV \
STIRLING_AOT_ENABLE="false" \
STIRLING_JVM_PROFILE="balanced" \
_JVM_OPTS_BALANCED="-XX:+ExitOnOutOfMemoryError -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/configs/heap_dumps -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:G1HeapRegionSize=4m -XX:G1PeriodicGCInterval=60000 -XX:+UseStringDeduplication -XX:+UseCompactObjectHeaders -XX:+ExplicitGCInvokesConcurrent -Dspring.threads.virtual.enabled=true -Djava.awt.headless=true" \
_JVM_OPTS_PERFORMANCE="-XX:+ExitOnOutOfMemoryError -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/configs/heap_dumps -XX:+UseShenandoahGC -XX:ShenandoahGCMode=generational -XX:+UseCompactObjectHeaders -XX:+UseStringDeduplication -XX:+AlwaysPreTouch -XX:+ExplicitGCInvokesConcurrent -Dspring.threads.virtual.enabled=true -Djava.awt.headless=true" \
JAVA_CUSTOM_OPTS="" \
HOME=/home/stirlingpdfuser \
PUID=1000 \
PGID=1000 \
+1 -2
View File
@@ -106,12 +106,11 @@ RUN set -eux; \
RUN echo "${VERSION_TAG:-dev}" > /etc/stirling_version
# Environment variables
ENV VERSION_TAG=$VERSION_TAG \
ENV \
STIRLING_AOT_ENABLE="false" \
STIRLING_JVM_PROFILE="balanced" \
_JVM_OPTS_BALANCED="-XX:+ExitOnOutOfMemoryError -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/configs/heap_dumps -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:G1HeapRegionSize=4m -XX:G1PeriodicGCInterval=60000 -XX:+UseStringDeduplication -XX:+UseCompactObjectHeaders -XX:+ExplicitGCInvokesConcurrent -Dspring.threads.virtual.enabled=true -Djava.awt.headless=true" \
_JVM_OPTS_PERFORMANCE="-XX:+ExitOnOutOfMemoryError -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/configs/heap_dumps -XX:+UseShenandoahGC -XX:ShenandoahGCMode=generational -XX:+UseCompactObjectHeaders -XX:+UseStringDeduplication -XX:+AlwaysPreTouch -XX:+ExplicitGCInvokesConcurrent -Dspring.threads.virtual.enabled=true -Djava.awt.headless=true" \
JAVA_CUSTOM_OPTS="" \
HOME=/home/stirlingpdfuser \
PUID=1000 \
PGID=1000 \
+1 -2
View File
@@ -105,12 +105,11 @@ RUN set -eux; \
RUN echo "${VERSION_TAG:-dev}" > /etc/stirling_version
# Environment variables
ENV VERSION_TAG=$VERSION_TAG \
ENV \
STIRLING_AOT_ENABLE="false" \
STIRLING_JVM_PROFILE="balanced" \
_JVM_OPTS_BALANCED="-XX:+ExitOnOutOfMemoryError -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/configs/heap_dumps -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:G1HeapRegionSize=4m -XX:G1PeriodicGCInterval=60000 -XX:+UseStringDeduplication -XX:+UseCompactObjectHeaders -XX:+ExplicitGCInvokesConcurrent -Dspring.threads.virtual.enabled=true -Djava.awt.headless=true" \
_JVM_OPTS_PERFORMANCE="-XX:+ExitOnOutOfMemoryError -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/configs/heap_dumps -XX:+UseShenandoahGC -XX:ShenandoahGCMode=generational -XX:+UseCompactObjectHeaders -XX:+UseStringDeduplication -XX:+AlwaysPreTouch -XX:+ExplicitGCInvokesConcurrent -Dspring.threads.virtual.enabled=true -Djava.awt.headless=true" \
JAVA_CUSTOM_OPTS="" \
HOME=/home/stirlingpdfuser \
PUID=1000 \
PGID=1000 \
+4 -2
View File
@@ -83,15 +83,17 @@ LABEL org.opencontainers.image.title="Stirling-PDF Ultra-Lite" \
org.opencontainers.image.version="${VERSION_TAG}" \
org.opencontainers.image.keywords="PDF, manipulation, ultra-lite, API, Spring Boot, React"
# Version file for scripts (init-without-ocr.sh reads /etc/stirling_version).
RUN echo "${VERSION_TAG:-dev}" > /etc/stirling_version
# Environment Variables
# NOTE: Memory flags (InitialRAMPercentage, MaxRAMPercentage, MaxMetaspaceSize)
# are computed dynamically by init-without-ocr.sh based on container memory limits.
ENV VERSION_TAG=$VERSION_TAG \
ENV \
STIRLING_AOT_ENABLE="false" \
STIRLING_JVM_PROFILE="balanced" \
_JVM_OPTS_BALANCED="-XX:+ExitOnOutOfMemoryError -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/configs/heap_dumps -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:G1HeapRegionSize=4m -XX:G1PeriodicGCInterval=60000 -XX:+UseStringDeduplication -XX:+UseCompactObjectHeaders -XX:+ExplicitGCInvokesConcurrent -Dspring.threads.virtual.enabled=true -Djava.awt.headless=true" \
_JVM_OPTS_PERFORMANCE="-XX:+ExitOnOutOfMemoryError -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/configs/heap_dumps -XX:+UseShenandoahGC -XX:ShenandoahGCMode=generational -XX:+UseCompactObjectHeaders -XX:+UseStringDeduplication -XX:+AlwaysPreTouch -XX:+ExplicitGCInvokesConcurrent -Dspring.threads.virtual.enabled=true -Djava.awt.headless=true" \
JAVA_CUSTOM_OPTS="" \
HOME=/home/stirlingpdfuser \
PUID=1000 \
PGID=1000 \
+7 -4
View File
@@ -382,10 +382,13 @@ start_unoserver_pool() {
}
# ---------- VERSION_TAG ----------
# Load VERSION_TAG from file if not provided via environment.
if [ -z "${VERSION_TAG:-}" ] && [ -f /etc/stirling_version ]; then
VERSION_TAG="$(tr -d '\r\n' < /etc/stirling_version)"
export VERSION_TAG
# The version baked into the image wins over a VERSION_TAG carried over from a previous
# container by the container manager.
INIT_SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
if [ -r "${INIT_SCRIPT_DIR}/resolve-version-tag.sh" ]; then
# shellcheck source=resolve-version-tag.sh
. "${INIT_SCRIPT_DIR}/resolve-version-tag.sh"
resolve_version_tag
fi
# ---------- AOT ----------
+29
View File
@@ -0,0 +1,29 @@
#!/bin/bash
# Resolve the version of the image that is actually running.
#
# The version baked into the image at build time wins over VERSION_TAG from the
# environment. Container managers (Portainer, Synology, and friends) carry the previous
# container's environment across an image update, so a VERSION_TAG left behind there
# used to mask the release that was really pulled - see issue #3460. The environment is
# only consulted when the image has no version file, which keeps dev and source builds
# working.
STIRLING_VERSION_FILE="${STIRLING_VERSION_FILE:-/etc/stirling_version}"
resolve_version_tag() {
local baked=""
if [ -r "${STIRLING_VERSION_FILE}" ]; then
baked="$(tr -d '\r\n' < "${STIRLING_VERSION_FILE}")"
fi
if [ -n "$baked" ]; then
if [ -n "${VERSION_TAG:-}" ] && [ "${VERSION_TAG}" != "$baked" ]; then
printf '%s\n' \
"[init][warn] Ignoring VERSION_TAG=${VERSION_TAG} from the environment; this image is ${baked}." \
"[init][warn] Remove VERSION_TAG from your container configuration - it is set by the image." >&2
fi
VERSION_TAG="$baked"
export VERSION_TAG
elif [ -n "${VERSION_TAG:-}" ]; then
export VERSION_TAG
fi
}
+64
View File
@@ -0,0 +1,64 @@
#!/bin/bash
# Unit tests for scripts/resolve-version-tag.sh (issue #3460).
#
# Container managers such as Portainer and Synology carry the previous container's
# environment across an image update. A VERSION_TAG left behind that way used to win
# over the version baked into the new image, so the app kept reporting - and, on the
# images that still downloaded a per-version jar, kept running - the old release.
set -uo pipefail
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
HELPER="${REPO_ROOT}/scripts/resolve-version-tag.sh"
failures=0
run_case() {
local name="$1" baked="$2" env_value="$3" expected="$4"
local tmp actual
tmp="$(mktemp -d)"
if [ "$baked" != "<none>" ]; then
printf '%s\n' "$baked" > "${tmp}/stirling_version"
fi
actual="$(
set +u
export STIRLING_VERSION_FILE="${tmp}/stirling_version"
if [ "$env_value" != "<unset>" ]; then
export VERSION_TAG="$env_value"
else
unset VERSION_TAG
fi
# shellcheck source=/dev/null
. "$HELPER"
resolve_version_tag 2>/dev/null
printf '%s' "${VERSION_TAG:-<unset>}"
)"
rm -rf "$tmp"
if [ "$actual" = "$expected" ]; then
printf 'ok - %s\n' "$name"
else
printf 'FAIL - %s (expected %s, got %s)\n' "$name" "$expected" "$actual"
failures=$((failures + 1))
fi
}
if [ ! -r "$HELPER" ]; then
printf 'FAIL - %s is missing\n' "$HELPER"
exit 1
fi
run_case "baked version wins over a stale environment value" "2.14.3" "0.44.0" "2.14.3"
run_case "baked version is used when nothing is in the environment" "2.14.3" "<unset>" "2.14.3"
run_case "matching environment value is kept" "2.14.3" "2.14.3" "2.14.3"
run_case "environment value is honoured when the image has no version file" "<none>" "0.44.0" "0.44.0"
run_case "empty version file does not blank out the environment value" "" "0.44.0" "0.44.0"
run_case "no version anywhere leaves VERSION_TAG unset" "<none>" "<unset>" "<unset>"
if [ "$failures" -gt 0 ]; then
printf '\n%d test(s) failed\n' "$failures"
exit 1
fi
printf '\nall tests passed\n'