Deployment als Docker-Container

Ein Container liefert Startseite und REST-API über Port 8080 aus: Das
Dockerfile baut das Frontend mit Node, legt das Ergebnis in die statischen
Ressourcen des Backends und packt beides mit Maven zum Jar; die Laufzeit-
stufe enthält nur ein JRE und das Jar, ausgeführt als Benutzer swyx.

Die beiden Build-Stufen laufen auf $BUILDPLATFORM, also nativ auf dem
bauenden Rechner - JS-Bundle und Jar sind architekturunabhängig. Nur das
Laufzeit-Image wird für die Zielarchitektur gezogen, was beim Bauen für
linux/amd64 auf einem ARM-Mac die Emulation spart.

docker_push.sh liest die Version aus backend/pom.xml, baut für linux/amd64
und pusht in die Registry.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-24 14:17:44 +02:00
co-authored by Claude Opus 5
parent 6e9de54119
commit 2a2bce860e
3 changed files with 209 additions and 0 deletions
Executable
+112
View File
@@ -0,0 +1,112 @@
#!/usr/bin/env bash
set -euo pipefail
readonly SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
# Paket-Registry des Gitea auf gitea.appcreation.de; der Pfad ist dort
# <Host>/<Besitzer>/<Image>.
readonly REGISTRY_IMAGE="gitea.appcreation.de/appcreation/swyxweb"
readonly BACKEND_DIR="${SCRIPT_DIR}/backend"
readonly PLATFORM="linux/amd64"
usage() {
cat <<'EOF'
Verwendung:
./docker_push.sh [x.y.z] [--dry-run]
Beispiel:
./docker_push.sh 0.9.13
./docker_push.sh
./docker_push.sh 0.9.13 --dry-run # nur bauen, nicht pushen
Voraussetzungen:
- Docker Buildx ist installiert
- Login zur Registry wurde bereits ausgeführt:
docker login gitea.appcreation.de
Ohne Versionsargument wird die Version aus backend/pom.xml verwendet.
Gebaut wird das Dockerfile im Wurzelverzeichnis: Es übersetzt Frontend *und*
Backend selbst, ein vorheriger lokaler Maven- oder npm-Lauf ist also nicht
nötig. Der SwyxTray-Mock ist im Image nicht enthalten (Profil "mock").
EOF
}
fail() {
echo "Fehler: $*" >&2
exit 1
}
require_command() {
command -v "$1" >/dev/null 2>&1 || fail "'$1' wurde nicht gefunden."
}
# Die Version steht in backend/pom.xml; ausgelesen wird sie mit dem Maven-
# Wrapper des Backends (backend/mvnw), nicht mit einem global installierten Maven.
resolve_pom_version() {
[[ -x "${BACKEND_DIR}/mvnw" ]] || fail "'${BACKEND_DIR}/mvnw' wurde nicht gefunden oder ist nicht ausführbar."
local version
version="$(
cd "${BACKEND_DIR}" && ./mvnw -q -DforceStdout help:evaluate -Dexpression=project.version \
| awk 'NF { last = $0 } END { print last }'
)"
[[ -n "${version}" ]] || fail "Version konnte nicht aus der pom.xml ermittelt werden."
echo "${version}"
}
VERSION=""
DRY_RUN=false
for arg in "$@"; do
case "${arg}" in
-h|--help)
usage
exit 0
;;
--dry-run)
DRY_RUN=true
;;
-*)
fail "Unbekannte Option '${arg}'."
;;
*)
[[ -z "${VERSION}" ]] || fail "Es ist nur eine Versionsnummer erlaubt."
VERSION="${arg}"
;;
esac
done
[[ -n "${VERSION}" ]] || VERSION="$(resolve_pom_version)"
# -SNAPSHOT ist zugelassen, weil die pom.xml zurzeit 0.0.1-SNAPSHOT trägt.
if [[ ! "${VERSION}" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-SNAPSHOT)?$ ]]; then
fail "Versionsnummer muss das Format x.y.z oder x.y.z-SNAPSHOT haben (war: '${VERSION}')."
fi
require_command docker
docker buildx version >/dev/null 2>&1 || fail "Docker Buildx ist nicht verfügbar."
cd "${SCRIPT_DIR}"
if [[ "${DRY_RUN}" == true ]]; then
echo "Baue Image ${REGISTRY_IMAGE}:${VERSION} für ${PLATFORM} (dry run, kein Push) ..."
docker buildx build \
--platform "${PLATFORM}" \
-f "${SCRIPT_DIR}/Dockerfile" \
-t "${REGISTRY_IMAGE}:${VERSION}" \
"${SCRIPT_DIR}"
echo "Fertig gebaut, nicht gepusht: ${REGISTRY_IMAGE}:${VERSION}"
exit 0
fi
echo "Baue und pushe Image ${REGISTRY_IMAGE}:${VERSION} für ${PLATFORM} ..."
docker buildx build \
--platform "${PLATFORM}" \
-f "${SCRIPT_DIR}/Dockerfile" \
-t "${REGISTRY_IMAGE}:${VERSION}" \
--push \
"${SCRIPT_DIR}"
echo "Fertig: ${REGISTRY_IMAGE}:${VERSION}"