Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
75 changes: 75 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
{
// Devcontainer-Sicherheitsmodell: Push aus Container ist hart geblockt (DEVCONTAINER=true + pre-push-Hook).
// Keine Credentials im Image, kein SSH-Agent-Forwarding, keine Cred-Mounts.
// Quelle: ~/.claude/vault/concepts/devcontainer-architektur.md
"name": "java-identifiers",

// 2026-05-13: JDK 25 LTS zum Zeitpunkt dieser Vorlage. Verfuegbarkeit pruefen mit:
// docker manifest inspect mcr.microsoft.com/devcontainers/java:25-bookworm
// Fallback falls 25er-Tag noch nicht verfuegbar: java:21-bookworm.
// Microsoft-Java-Bookworm bringt JDK mit, **kein Maven** — wird im post-create per apt installiert.
"image": "mcr.microsoft.com/devcontainers/java:25-bookworm",

// Features:
// - docker-outside-of-docker: docker-CLI im Container + Sock-Permissions/Group fuer nonroot-User.
// Voraussetzung fuer Testcontainers, jib, ko, Buildpacks (alles was Sibling-Container startet).
// Maven wird absichtlich NICHT ueber `features/java:1` installiert: das SDKMAN-Feature scheitert
// in manchen buildx-Sandbox-Netzen am Internet-Healthcheck. apt im post-create ist robust und
// liefert Maven 3.8.7 (Debian Bookworm). Wer ein anderes Maven braucht: Apache-Tarball im
// post-create unpacken oder eigenen Layer im Dockerfile.
"features": {
"ghcr.io/devcontainers/features/docker-outside-of-docker:1": {}
},

// Sicherheitsmarker: Hook .githooks/pre-push prueft diesen Wert und blockt bei "true".
// JDWP-Opts: agent listet auf 5005 fuer Remote-Debugging. suspend=n -> Build startet sofort.
// TESTCONTAINERS_HOST_OVERRIDE: Sibling-Container (Ryuk, Test-DB) sind ueber Host-Gateway
// erreichbar, nicht ueber default-bridge `172.17.0.1`. runArgs unten haengt `host.docker.internal`
// an /etc/hosts (Linux-Equivalent zum Mac/Win-Default). Wenn das Repo keinen Testcontainers-Pfad
// hat (kein jOOQ-Generate o.ae.), kann der Override entfernt werden — schadet aber nicht.
// JAVA_HOME: Eclipse Temurin (Adoptium) statt Microsoft OpenJDK. post-create.sh installiert
// Temurin parallel zum Microsoft-JDK aus dem Image. Begruendung: Distributions-Konsistenz mit
// CI (setup-java distribution=temurin) und Toolchains, die das Temurin-JDK-Layout erwarten
// (z.B. JAVA_HOME/Packages). Microsoft-OpenJDK liegt ungenutzt parallel — IDE-Indexing nimmt JAVA_HOME.
"containerEnv": {
"DEVCONTAINER": "true",
"MAVEN_OPTS": "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005",
"TESTCONTAINERS_HOST_OVERRIDE": "host.docker.internal",
"JAVA_HOME": "/usr/lib/jvm/temurin-25-jdk-amd64"
},

// - --add-host: Linux-Equivalent zu Mac/Win `host.docker.internal`. Fuer Testcontainers.
// - --name: fester Container-Name (`devcontainer-<basename>`) — verbessert `docker ps`-Lesbarkeit.
// Konflikte handhabt devcontainer-CLI via --remove-existing-container.
// Unterstuetzt `./dev down` (siehe dev-skripte.md).
"runArgs": [
"--add-host=host.docker.internal:host-gateway",
"--name", "devcontainer-${localWorkspaceFolderBasename}"
],

// 5005 = JDWP (Remote JVM Debug, IntelliJ/VS Code). App-Port hier ergaenzen, z.B. 8080.
"forwardPorts": [5005],

// Mounts:
// - docker.sock: Daemon-Zugriff fuer Testcontainers + Build-Tools mit Container-Targets.
// Trade-off + Anti-Pattern (NIE im Production-Image): vault/concepts/devcontainer-architektur.md "Docker-Zugriff im Container".
// - m2 Named Volume: persistenter Maven-Cache. Permissions im post-create gechownt
// (Docker-Named-Volumes sind root:root by default; vscode-User braucht Schreibzugriff).
// - target/ NICHT als Root-Volume bei Multi-Module-Repos (jedes Sub-Modul hat eigenes target/).
"mounts": [
"source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind",
"source=devcontainer-${localWorkspaceFolderBasename}-m2,target=/home/vscode/.m2,type=volume"
],

// Maven via apt + Volume-chown + Push-Block-Hook. Script erlaubt sauberes Fehler-Handling.
"postCreateCommand": ".devcontainer/post-create.sh",

"customizations": {
"vscode": {
"extensions": [
"vscjava.vscode-java-pack",
"vscjava.vscode-maven"
]
}
}
}
68 changes: 68 additions & 0 deletions .devcontainer/post-create.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#!/usr/bin/env bash
set -euo pipefail

# Devcontainer Post-Create-Hook (java-maven Template).
# Idempotent — wird bei jeder Container-Erstellung ausgefuehrt.

echo "[post-create] Fixing named-volume permissions (m2-cache)..."
# Docker-Named-Volumes werden mit root:root erstellt; der vscode-User braucht Schreibzugriff.
sudo chown -R vscode:vscode /home/vscode/.m2

# Eclipse Temurin via Adoptium apt-Repo. Hintergrund:
# Microsoft-Java-Image bringt Microsoft OpenJDK mit — manche Gradle/Plugin-Toolchains erwarten
# das Standard-JDK-Layout (JAVA_HOME/Packages, Temurin-Style). Auch generelle Distributions-
# Konsistenz mit CI (setup-java mit distribution=temurin) ist erwuenscht.
# Adoptium installiert nach /usr/lib/jvm/temurin-{ver}-jdk-amd64. devcontainer.json setzt
# JAVA_HOME entsprechend. Microsoft-OpenJDK bleibt ungenutzt parallel im Image.
TEMURIN_VERSION=25
TEMURIN_HOME="/usr/lib/jvm/temurin-${TEMURIN_VERSION}-jdk-amd64"

if [ ! -d "$TEMURIN_HOME" ]; then
echo "[post-create] Installing Eclipse Temurin ${TEMURIN_VERSION} (Adoptium)..."
sudo apt-get update -qq
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
wget apt-transport-https gpg >/dev/null
wget -qO - https://packages.adoptium.net/artifactory/api/gpg/key/public \
| sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/adoptium.gpg
echo "deb https://packages.adoptium.net/artifactory/deb bookworm main" \
| sudo tee /etc/apt/sources.list.d/adoptium.list > /dev/null
sudo apt-get update -qq
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
"temurin-${TEMURIN_VERSION}-jdk" >/dev/null
echo "[post-create] Temurin ${TEMURIN_VERSION} installed at $TEMURIN_HOME."
else
echo "[post-create] Temurin ${TEMURIN_VERSION} already present."
fi

echo "[post-create] Installing Maven via apt..."
# Microsoft-Java-Bookworm hat JDK, aber kein Maven vorinstalliert.
# `features/java:1` mit installMaven schlaegt in manchen buildx-Sandbox-Netzen am
# SDKMAN-Internet-Healthcheck fehl — apt ist robust und liefert Maven 3.8.7 (Bookworm).
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends maven >/dev/null
echo "[post-create] Maven installed: $(mvn -version 2>&1 | grep -E '^Apache Maven' | head -1)"

echo "[post-create] Java versions:"
echo " JAVA_HOME: ${JAVA_HOME:-not set}"
echo " active java: $(java -version 2>&1 | head -1)"

# IntelliJ Native Devcontainer Mode-Fix: das JetBrains-Backend laeuft im Container als root
# (Container-Default-User), waehrend mvn/gradle im Terminal als vscode-User laufen (devcontainer
# remoteUser). Der Indexer sucht in /root/.m2/repository/ — leer, weil Maven nach
# /home/vscode/.m2/repository/ schreibt. Folge: alle Dependencies im IntelliJ-Editor rot.
# Symlink /root/.m2 -> /home/vscode/.m2 macht beide User auf denselben m2-Cache zeigen.
# Idempotent: -f ueberschreibt eventuell vorhandenen Pfad (Dir oder Symlink).
echo "[post-create] Symlinking /root/.m2 -> /home/vscode/.m2 (IntelliJ-Backend-Fix)..."
sudo ln -sfn /home/vscode/.m2 /root/.m2

echo "[post-create] Activating pre-push hook (core.hooksPath=.githooks)..."
if git rev-parse --git-dir >/dev/null 2>&1; then
git config core.hooksPath .githooks
echo "[post-create] core.hooksPath=.githooks set"
else
# Tritt typischerweise auf, wenn ein Sandbox-Worktree verwendet wird, dessen .git
# auf einen nicht gemounteten Eltern-Pfad zeigt. Produktive Klone (normale Checkouts)
# sind nicht betroffen.
echo "[post-create] WARN: git dir not reachable inside container."
echo "[post-create] WARN: Push-Block-Hook NICHT aktiv. Auf dem Host setzen:"
echo "[post-create] WARN: git config core.hooksPath .githooks"
fi
18 changes: 18 additions & 0 deletions .githooks/pre-push
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/usr/bin/env bash
# Devcontainer Push-Block-Hook.
# Verhindert git push aus dem Devcontainer.
# Host (WSL/Mac) pusht unblockiert -- DEVCONTAINER-Env nur im Container gesetzt.
# Quelle: ~/.claude/vault/concepts/devcontainer-architektur.md

if [ "${DEVCONTAINER:-}" = "true" ]; then
echo "" >&2
echo "[pre-push] BLOCKED: git push is not allowed from inside a devcontainer." >&2
echo "[pre-push]" >&2
echo "[pre-push] Devcontainer hat keine Credentials und darf keine haben." >&2
echo "[pre-push] Push vom Host (WSL-Distro / Mac), dort liegen die Token." >&2
echo "[pre-push]" >&2
echo "[pre-push] Konzept: ~/.claude/vault/concepts/devcontainer-architektur.md" >&2
echo "" >&2
exit 1
fi
exit 0
Loading