docker: skip redundant cmdeploy run on container restart

Replace the old IMAGE_VERSION_FILE/RUNNING_VERSION_FILE mechanism with a
single deploy fingerprint (image_version:sha256(chatmail.ini)) stored at
/etc/chatmail/.deploy-fingerprint. On restart, if the fingerprint matches
the last successful deploy, skip cmdeploy run entirely. The fingerprint
lives on the container's writable layer. On fresh containers, setting
CMDEPLOY_STAGES non-empty in env forces a deploy run regardless of
fingerprint.

Also narrow the /home volume mount to /home/vmail.
This commit is contained in:
j4n
2026-02-17 15:09:48 +01:00
parent bc19966801
commit 2e23fadb54
4 changed files with 30 additions and 33 deletions

View File

@@ -18,40 +18,37 @@ fi
# Fix ownership for bind-mounted keys (host opendkim UID may differ from container)
chown -R opendkim:opendkim /etc/dkimkeys
# Journald: forward to console for docker logs
grep -q '^ForwardToConsole=yes' /etc/systemd/journald.conf \
|| echo "ForwardToConsole=yes" >> /etc/systemd/journald.conf
systemctl restart systemd-journald
# Create chatmail.ini (skips if file already exists, e.g. volume-mounted)
mkdir -p "$(dirname "$CHATMAIL_INI")"
if [ ! -f "$CHATMAIL_INI" ]; then
$CMDEPLOY init --config "$CHATMAIL_INI" "$MAIL_DOMAIN"
fi
# Auto-detect image upgrades: if the image version changed since last run,
# include the install stage so new packages/binaries are picked up.
# --- Deploy fingerprint: skip cmdeploy run if nothing changed ---
# On restart with identical image+config, systemd already brings up all
# enabled services — the full cmdeploy run is redundant (~30s saved).
# The install stage runs at image build time (Dockerfile), so only
# configure+activate are needed here.
IMAGE_VERSION_FILE="/etc/chatmail-image-version"
RUNNING_VERSION_FILE="/home/.chatmail-running-version"
CMDEPLOY_STAGES="${CMDEPLOY_STAGES:-configure,activate}"
if [ -f "$IMAGE_VERSION_FILE" ]; then
image_ver=$(cat "$IMAGE_VERSION_FILE")
running_ver=""
if [ -f "$RUNNING_VERSION_FILE" ]; then
running_ver=$(cat "$RUNNING_VERSION_FILE")
fi
if [ "$image_ver" != "$running_ver" ]; then
echo "[INFO] Image version changed ($running_ver -> $image_ver), adding install stage."
case "$CMDEPLOY_STAGES" in
*install*) ;; # already includes install
*) CMDEPLOY_STAGES="install,$CMDEPLOY_STAGES" ;;
esac
fi
fi
export CMDEPLOY_STAGES
$CMDEPLOY run --config "$CHATMAIL_INI" --ssh-host @local
FINGERPRINT_FILE="/etc/chatmail/.deploy-fingerprint"
image_ver="none"
[ -f "$IMAGE_VERSION_FILE" ] && image_ver=$(cat "$IMAGE_VERSION_FILE")
config_hash=$(sha256sum "$CHATMAIL_INI" | cut -c1-16)
current_fp="${image_ver}:${config_hash}"
# Record successful version after deploy
if [ -f "$IMAGE_VERSION_FILE" ]; then
cp "$IMAGE_VERSION_FILE" "$RUNNING_VERSION_FILE"
# CMDEPLOY_STAGES non-empty in env = operator override → always run.
# Otherwise, if fingerprint matches the last successful deploy, skip.
if [ -z "${CMDEPLOY_STAGES:-}" ] \
&& [ -f "$FINGERPRINT_FILE" ] \
&& [ "$(cat "$FINGERPRINT_FILE")" = "$current_fp" ]; then
echo "[INFO] No changes detected ($current_fp), skipping deploy."
else
export CMDEPLOY_STAGES="${CMDEPLOY_STAGES:-configure,activate}"
$CMDEPLOY run --config "$CHATMAIL_INI" --ssh-host @local
echo "$current_fp" > "$FINGERPRINT_FILE"
fi
# Journald: forward to console for docker logs (idempotent)
grep -q '^ForwardToConsole=yes' /etc/systemd/journald.conf \
|| echo "ForwardToConsole=yes" >> /etc/systemd/journald.conf
systemctl restart systemd-journald