docs: document the runtime-loader image (moved here from cameleer-server)
Some checks failed
CI / build (push) Successful in 3m10s
CI / docker (push) Failing after 8s

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").
This commit is contained in:
hsiegeln
2026-04-28 13:05:49 +02:00
parent ac8d628271
commit 6ac06d6859
2 changed files with 8 additions and 6 deletions

View File

@@ -70,6 +70,7 @@ PostgreSQL (Flyway): `src/main/resources/db/migration/`
- `cameleer-logto` — custom Logto with sign-in UI baked in - `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-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-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 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`. - `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. - 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:start --> <!-- gitnexus:start -->
# GitNexus — Code Intelligence # 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. > 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: "<error or symptom>"})` — find execution flows related to the issue 1. `gitnexus_query({query: "<error or symptom>"})` — find execution flows related to the issue
2. `gitnexus_context({name: "<suspect function>"})` — see all callers, callees, and process participation 2. `gitnexus_context({name: "<suspect function>"})` — 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 4. For regressions: `gitnexus_detect_changes({scope: "compare", base_ref: "main"})` — see what your branch changed
## When Refactoring ## When Refactoring
@@ -137,10 +138,10 @@ This project is indexed by GitNexus as **vendor-admin-account** (3510 symbols, 7
| Resource | Use for | | Resource | Use for |
|----------|---------| |----------|---------|
| `gitnexus://repo/vendor-admin-account/context` | Codebase overview, check index freshness | | `gitnexus://repo/cameleer-saas/context` | Codebase overview, check index freshness |
| `gitnexus://repo/vendor-admin-account/clusters` | All functional areas | | `gitnexus://repo/cameleer-saas/clusters` | All functional areas |
| `gitnexus://repo/vendor-admin-account/processes` | All execution flows | | `gitnexus://repo/cameleer-saas/processes` | All execution flows |
| `gitnexus://repo/vendor-admin-account/process/{name}` | Step-by-step execution trace | | `gitnexus://repo/cameleer-saas/process/{name}` | Step-by-step execution trace |
## Self-Check Before Finishing ## Self-Check Before Finishing

View File

@@ -67,6 +67,7 @@ Key files:
- `DeploymentExecutor.java` (in cameleer-server) — async staged deployment, runtime type auto-detection - `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. - `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-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) - `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 - `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) - Docker socket access: `group_add: ["0"]` in docker-compose.dev.yml (not root group membership in Dockerfile)