From 6ac06d6859b9b7a8a3e68f3d8374438ba71e9389 Mon Sep 17 00:00:00 2001 From: hsiegeln <37154749+hsiegeln@users.noreply.github.com> Date: Tue, 28 Apr 2026 13:05:49 +0200 Subject: [PATCH] docs: document the runtime-loader image (moved here from cameleer-server) Note that the loader source now lives at docker/runtime-loader/, that the contract is owned by cameleer-server's DockerRuntimeOrchestrator (don't change env vars / mount path / exit codes without a coordinated commit there), and that cameleer-server's LoaderHardeningIT is the cross-repo regression guard. Also document the chown-/app/jars line (strip it and tenant deploys break with "wget: Permission denied"). --- CLAUDE.md | 13 +++++++------ docker/CLAUDE.md | 1 + 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 0c83395..8da732b 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -70,6 +70,7 @@ PostgreSQL (Flyway): `src/main/resources/db/migration/` - `cameleer-logto` — custom Logto with sign-in UI baked in - `cameleer-server` / `cameleer-server-ui` — provisioned per-tenant (not in compose, created by `DockerTenantProvisioner`) - `cameleer-runtime-base` — base image for deployed apps (agent JAR + `cameleer-log-appender.jar` + JRE). CI downloads latest agent and log appender SNAPSHOTs from Gitea Maven registry. The Dockerfile ENTRYPOINT is overridden by `DockerRuntimeOrchestrator` at container creation; agent config uses `CAMELEER_AGENT_*` env vars set by `DeploymentExecutor`. + - `cameleer-runtime-loader` (`docker/runtime-loader/`) — tiny init-container image (busybox + 26-line `entrypoint.sh`) consumed as a sidecar by `DockerRuntimeOrchestrator` in **cameleer-server**. Per-replica: fetches the tenant JAR from a signed URL into a named volume RW-mounted at `/app/jars`, then exits 0; the main runtime container mounts the same volume RO. Source moved here from cameleer-server in April 2026 to colocate with the other infra/sidecar images. **Contract is owned by cameleer-server** (env vars `ARTIFACT_URL` + `ARTIFACT_EXPECTED_SIZE`, output path `/app/jars/app.jar`, exit 0/non-zero semantics) — don't change those without a coordinated commit on the cameleer-server side. cameleer-server's `LoaderHardeningIT` is the cross-repo regression guard; it pulls `:latest` and asserts exit 0 under the orchestrator's hardening shape. - Docker builds: `--no-cache`, `--provenance=false` for Gitea compatibility - `docker-compose.yml` (root) — thin dev overlay (ports, volume mounts, `SPRING_PROFILES_ACTIVE: dev`). Chained on top of production templates from the installer submodule via `COMPOSE_FILE` in `.env`. - Installer is a **git submodule** at `installer/` pointing to `cameleer/cameleer-saas-installer` (public repo). Compose templates live there — single source of truth, no duplication. Run `git submodule update --remote installer` to pull template updates. @@ -82,7 +83,7 @@ PostgreSQL (Flyway): `src/main/resources/db/migration/` # GitNexus — Code Intelligence -This project is indexed by GitNexus as **vendor-admin-account** (3510 symbols, 7678 relationships, 298 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely. +This project is indexed by GitNexus as **cameleer-saas** (3624 symbols, 7877 relationships, 300 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely. > If any GitNexus tool warns the index is stale, run `npx gitnexus analyze` in terminal first. @@ -98,7 +99,7 @@ This project is indexed by GitNexus as **vendor-admin-account** (3510 symbols, 7 1. `gitnexus_query({query: ""})` — find execution flows related to the issue 2. `gitnexus_context({name: ""})` — see all callers, callees, and process participation -3. `READ gitnexus://repo/vendor-admin-account/process/{processName}` — trace the full execution flow step by step +3. `READ gitnexus://repo/cameleer-saas/process/{processName}` — trace the full execution flow step by step 4. For regressions: `gitnexus_detect_changes({scope: "compare", base_ref: "main"})` — see what your branch changed ## When Refactoring @@ -137,10 +138,10 @@ This project is indexed by GitNexus as **vendor-admin-account** (3510 symbols, 7 | Resource | Use for | |----------|---------| -| `gitnexus://repo/vendor-admin-account/context` | Codebase overview, check index freshness | -| `gitnexus://repo/vendor-admin-account/clusters` | All functional areas | -| `gitnexus://repo/vendor-admin-account/processes` | All execution flows | -| `gitnexus://repo/vendor-admin-account/process/{name}` | Step-by-step execution trace | +| `gitnexus://repo/cameleer-saas/context` | Codebase overview, check index freshness | +| `gitnexus://repo/cameleer-saas/clusters` | All functional areas | +| `gitnexus://repo/cameleer-saas/processes` | All execution flows | +| `gitnexus://repo/cameleer-saas/process/{name}` | Step-by-step execution trace | ## Self-Check Before Finishing diff --git a/docker/CLAUDE.md b/docker/CLAUDE.md index e09483e..9a5614f 100644 --- a/docker/CLAUDE.md +++ b/docker/CLAUDE.md @@ -67,6 +67,7 @@ Key files: - `DeploymentExecutor.java` (in cameleer-server) — async staged deployment, runtime type auto-detection - `DockerRuntimeOrchestrator.java` (in cameleer-server) — Docker client, container lifecycle, builds runtime-type-specific entrypoints (spring-boot uses `-cp` + `PropertiesLauncher` with `-Dloader.path` for log appender; quarkus uses `-jar`; plain-java uses `-cp` + detected main class; native exec directly). Overrides the Dockerfile ENTRYPOINT. - `docker/runtime-base/Dockerfile` — base image with agent JAR + `cameleer-log-appender.jar` + JRE. The Dockerfile ENTRYPOINT (`-jar /app/app.jar`) is a fallback — `DockerRuntimeOrchestrator` overrides it at container creation. +- `docker/runtime-loader/Dockerfile` + `entrypoint.sh` — tiny per-replica init-container image (busybox + 26-line shell). Consumed by cameleer-server's `DockerRuntimeOrchestrator` as a sidecar that fetches the tenant JAR from a signed URL into a named volume RW-mounted at `/app/jars`, then exits 0. The main runtime container mounts that volume RO. Image lives here so all infra/sidecar image builds are colocated, but the **runtime contract** (env vars `ARTIFACT_URL` + `ARTIFACT_EXPECTED_SIZE`, output path `/app/jars/app.jar`, exit 0/non-zero semantics) is owned by cameleer-server's orchestrator. Don't change those without a coordinated commit on the cameleer-server side; cameleer-server's `LoaderHardeningIT` is the cross-repo regression guard. Pre-creates `/app/jars` owned by `loader:loader` (UID 1000) so the orchestrator's fresh named volume initialises with that ownership — stripping that line breaks tenant deploys with "wget: Permission denied". - `RuntimeDetector.java` (in cameleer-server) — detects runtime type from JAR manifest `Main-Class`; derives correct `PropertiesLauncher` package (Spring Boot 3.2+ vs pre-3.2) - `ServerApiClient.java` — M2M token acquisition for SaaS->server API calls (agent status). Uses `X-Cameleer-Protocol-Version: 1` header - Docker socket access: `group_add: ["0"]` in docker-compose.dev.yml (not root group membership in Dockerfile)