fix: provisioned server containers — strip-prefix, Docker socket, env
All checks were successful
CI / build (push) Successful in 1m14s
CI / docker (push) Successful in 34s

- Add Traefik strip-prefix middleware so /t/{slug}/api -> /api on server
- Add priority to routers (server API=10, UI=5) to prevent conflicts
- Mount Docker socket + group_add in server containers for app deployment
- Add JAR storage, Docker network, volume env vars for runtime orchestrator
- Use HashMap for labels (>10 entries exceeds Map.of limit)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-09 23:26:48 +02:00
parent 39c3b39711
commit 4087ce8f29

View File

@@ -114,14 +114,22 @@ public class DockerTenantProvisioner implements TenantProvisioner {
private void createServerContainer(TenantProvisionRequest req, String name) {
String slug = req.slug();
Map<String, String> labels = Map.of(
"traefik.enable", "true",
"traefik.http.routers.server-" + slug + ".rule", "PathPrefix(`/t/" + slug + "/api`) || PathPrefix(`/t/" + slug + "/actuator`)",
"traefik.http.routers.server-" + slug + ".tls", "true",
"traefik.http.services.server-" + slug + ".loadbalancer.server.port", "8081",
"cameleer.tenant", slug,
"cameleer.role", "server"
);
String prefix = "/t/" + slug;
// Traefik labels — need >10 entries, use HashMap
var labels = new java.util.HashMap<String, String>();
labels.put("traefik.enable", "true");
// Router: match /t/{slug}/api/* and /t/{slug}/actuator/*
labels.put("traefik.http.routers.server-" + slug + ".rule",
"PathPrefix(`" + prefix + "/api`) || PathPrefix(`" + prefix + "/actuator`)");
labels.put("traefik.http.routers.server-" + slug + ".tls", "true");
labels.put("traefik.http.routers.server-" + slug + ".priority", "10");
// Strip the /t/{slug} prefix so server sees /api/... and /actuator/...
labels.put("traefik.http.middlewares.server-strip-" + slug + ".stripprefix.prefixes", prefix);
labels.put("traefik.http.routers.server-" + slug + ".middlewares", "server-strip-" + slug);
labels.put("traefik.http.services.server-" + slug + ".loadbalancer.server.port", "8081");
labels.put("cameleer.tenant", slug);
labels.put("cameleer.role", "server");
List<String> env = List.of(
"SPRING_DATASOURCE_URL=" + props.datasourceUrl(),
@@ -140,12 +148,18 @@ public class DockerTenantProvisioner implements TenantProvisioner {
"CAMELEER_RUNTIME_ENABLED=true",
"CAMELEER_SERVER_URL=http://" + name + ":8081",
"CAMELEER_ROUTING_DOMAIN=" + props.publicHost(),
"CAMELEER_ROUTING_MODE=path"
"CAMELEER_ROUTING_MODE=path",
"CAMELEER_JAR_STORAGE_PATH=/data/jars",
"CAMELEER_DOCKER_NETWORK=" + props.networkName(),
"CAMELEER_JAR_DOCKER_VOLUME=cameleer-jars-" + slug
);
// Docker socket mount for app deployment within tenant server
HostConfig hostConfig = HostConfig.newHostConfig()
.withRestartPolicy(RestartPolicy.unlessStoppedRestart())
.withNetworkMode(props.networkName());
.withNetworkMode(props.networkName())
.withBinds(new Bind("/var/run/docker.sock", new Volume("/var/run/docker.sock")))
.withGroupAdd(List.of("0"));
CreateContainerResponse resp = docker.createContainerCmd(props.serverImage())
.withName(name)
@@ -159,7 +173,7 @@ public class DockerTenantProvisioner implements TenantProvisioner {
.withRetries(12))
.exec();
// Connect to traefik network
// Connect to traefik network with DNS alias
docker.connectToNetworkCmd()
.withNetworkId(props.traefikNetwork())
.withContainerId(resp.getId())
@@ -168,20 +182,23 @@ public class DockerTenantProvisioner implements TenantProvisioner {
}
private void createUiContainer(String slug, String uiName, String serverName) {
Map<String, String> labels = Map.of(
"traefik.enable", "true",
"traefik.http.routers.ui-" + slug + ".rule", "PathPrefix(`/t/" + slug + "`)",
"traefik.http.routers.ui-" + slug + ".tls", "true",
"traefik.http.routers.ui-" + slug + ".priority", "1",
"traefik.http.services.ui-" + slug + ".loadbalancer.server.port", "80",
"traefik.http.middlewares.ui-strip-" + slug + ".stripprefix.prefixes", "/t/" + slug,
"traefik.http.routers.ui-" + slug + ".middlewares", "ui-strip-" + slug,
"cameleer.tenant", slug,
"cameleer.role", "server-ui"
);
String prefix = "/t/" + slug;
var labels = new java.util.HashMap<String, String>();
labels.put("traefik.enable", "true");
// Router: catch-all for /t/{slug}/* (lower priority than server API)
labels.put("traefik.http.routers.ui-" + slug + ".rule", "PathPrefix(`" + prefix + "`)");
labels.put("traefik.http.routers.ui-" + slug + ".tls", "true");
labels.put("traefik.http.routers.ui-" + slug + ".priority", "5");
// Strip /t/{slug} prefix so UI sees /
labels.put("traefik.http.middlewares.ui-strip-" + slug + ".stripprefix.prefixes", prefix);
labels.put("traefik.http.routers.ui-" + slug + ".middlewares", "ui-strip-" + slug);
labels.put("traefik.http.services.ui-" + slug + ".loadbalancer.server.port", "80");
labels.put("cameleer.tenant", slug);
labels.put("cameleer.role", "server-ui");
List<String> env = List.of(
"BASE_PATH=/t/" + slug,
"BASE_PATH=" + prefix,
"API_URL=http://" + serverName + ":8081"
);