feat: expand ContainerRequest with cpuLimit, ports, restart policy, additional networks
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -18,6 +18,7 @@ import org.springframework.scheduling.annotation.Async;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@@ -99,11 +100,17 @@ public class DeploymentExecutor {
|
|||||||
baseImage,
|
baseImage,
|
||||||
jarPath,
|
jarPath,
|
||||||
dockerNetwork,
|
dockerNetwork,
|
||||||
|
List.of(),
|
||||||
envVars,
|
envVars,
|
||||||
labels,
|
labels,
|
||||||
parseMemoryLimitBytes(containerMemoryLimit),
|
parseMemoryLimitBytes(containerMemoryLimit),
|
||||||
|
null,
|
||||||
containerCpuShares,
|
containerCpuShares,
|
||||||
agentHealthPort);
|
null,
|
||||||
|
List.of(),
|
||||||
|
agentHealthPort,
|
||||||
|
"on-failure",
|
||||||
|
3);
|
||||||
|
|
||||||
String containerId = orchestrator.startContainer(request);
|
String containerId = orchestrator.startContainer(request);
|
||||||
waitForHealthy(containerId, healthCheckTimeout);
|
waitForHealthy(containerId, healthCheckTimeout);
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import com.github.dockerjava.api.model.Bind;
|
|||||||
import com.github.dockerjava.api.model.Frame;
|
import com.github.dockerjava.api.model.Frame;
|
||||||
import com.github.dockerjava.api.model.HealthCheck;
|
import com.github.dockerjava.api.model.HealthCheck;
|
||||||
import com.github.dockerjava.api.model.HostConfig;
|
import com.github.dockerjava.api.model.HostConfig;
|
||||||
|
import com.github.dockerjava.api.model.RestartPolicy;
|
||||||
import com.github.dockerjava.api.model.Volume;
|
import com.github.dockerjava.api.model.Volume;
|
||||||
import com.github.dockerjava.core.DefaultDockerClientConfig;
|
import com.github.dockerjava.core.DefaultDockerClientConfig;
|
||||||
import com.github.dockerjava.core.DockerClientImpl;
|
import com.github.dockerjava.core.DockerClientImpl;
|
||||||
@@ -59,7 +60,6 @@ public class DockerRuntimeOrchestrator implements RuntimeOrchestrator {
|
|||||||
List<String> envList = request.envVars().entrySet().stream()
|
List<String> envList = request.envVars().entrySet().stream()
|
||||||
.map(e -> e.getKey() + "=" + e.getValue()).toList();
|
.map(e -> e.getKey() + "=" + e.getValue()).toList();
|
||||||
|
|
||||||
// Volume bind: mount JAR into container
|
|
||||||
Bind jarBind = new Bind(request.jarPath(), new Volume("/app/app.jar"), AccessMode.ro);
|
Bind jarBind = new Bind(request.jarPath(), new Volume("/app/app.jar"), AccessMode.ro);
|
||||||
|
|
||||||
HostConfig hostConfig = HostConfig.newHostConfig()
|
HostConfig hostConfig = HostConfig.newHostConfig()
|
||||||
@@ -67,9 +67,17 @@ public class DockerRuntimeOrchestrator implements RuntimeOrchestrator {
|
|||||||
.withMemorySwap(request.memoryLimitBytes())
|
.withMemorySwap(request.memoryLimitBytes())
|
||||||
.withCpuShares(request.cpuShares())
|
.withCpuShares(request.cpuShares())
|
||||||
.withNetworkMode(request.network())
|
.withNetworkMode(request.network())
|
||||||
.withBinds(jarBind);
|
.withBinds(jarBind)
|
||||||
|
.withRestartPolicy(RestartPolicy.onFailureRestart(request.restartPolicyMaxRetries()));
|
||||||
|
|
||||||
var container = dockerClient.createContainerCmd(request.baseImage())
|
if (request.memoryReserveBytes() != null) {
|
||||||
|
hostConfig.withMemoryReservation(request.memoryReserveBytes());
|
||||||
|
}
|
||||||
|
if (request.cpuQuota() != null) {
|
||||||
|
hostConfig.withCpuQuota(request.cpuQuota());
|
||||||
|
}
|
||||||
|
|
||||||
|
var createCmd = dockerClient.createContainerCmd(request.baseImage())
|
||||||
.withName(request.containerName())
|
.withName(request.containerName())
|
||||||
.withEnv(envList)
|
.withEnv(envList)
|
||||||
.withLabels(request.labels() != null ? request.labels() : Map.of())
|
.withLabels(request.labels() != null ? request.labels() : Map.of())
|
||||||
@@ -77,17 +85,38 @@ public class DockerRuntimeOrchestrator implements RuntimeOrchestrator {
|
|||||||
.withHealthcheck(new HealthCheck()
|
.withHealthcheck(new HealthCheck()
|
||||||
.withTest(List.of("CMD-SHELL",
|
.withTest(List.of("CMD-SHELL",
|
||||||
"wget -qO- http://localhost:" + request.healthCheckPort() + "/cameleer/health || exit 1"))
|
"wget -qO- http://localhost:" + request.healthCheckPort() + "/cameleer/health || exit 1"))
|
||||||
.withInterval(10_000_000_000L) // 10s
|
.withInterval(10_000_000_000L)
|
||||||
.withTimeout(5_000_000_000L) // 5s
|
.withTimeout(5_000_000_000L)
|
||||||
.withRetries(3)
|
.withRetries(3)
|
||||||
.withStartPeriod(30_000_000_000L)) // 30s
|
.withStartPeriod(30_000_000_000L));
|
||||||
.exec();
|
|
||||||
|
|
||||||
|
if (request.exposedPorts() != null && !request.exposedPorts().isEmpty()) {
|
||||||
|
var ports = request.exposedPorts().stream()
|
||||||
|
.map(p -> com.github.dockerjava.api.model.ExposedPort.tcp(p))
|
||||||
|
.toArray(com.github.dockerjava.api.model.ExposedPort[]::new);
|
||||||
|
createCmd.withExposedPorts(ports);
|
||||||
|
}
|
||||||
|
|
||||||
|
var container = createCmd.exec();
|
||||||
dockerClient.startContainerCmd(container.getId()).exec();
|
dockerClient.startContainerCmd(container.getId()).exec();
|
||||||
|
|
||||||
|
if (request.additionalNetworks() != null) {
|
||||||
|
for (String net : request.additionalNetworks()) {
|
||||||
|
dockerClient.connectToNetworkCmd()
|
||||||
|
.withContainerId(container.getId())
|
||||||
|
.withNetworkId(net)
|
||||||
|
.exec();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
log.info("Started container {} ({})", request.containerName(), container.getId());
|
log.info("Started container {} ({})", request.containerName(), container.getId());
|
||||||
return container.getId();
|
return container.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DockerClient getDockerClient() {
|
||||||
|
return dockerClient;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void stopContainer(String containerId) {
|
public void stopContainer(String containerId) {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.cameleer3.server.core.runtime;
|
package com.cameleer3.server.core.runtime;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public record ContainerRequest(
|
public record ContainerRequest(
|
||||||
@@ -7,9 +8,15 @@ public record ContainerRequest(
|
|||||||
String baseImage,
|
String baseImage,
|
||||||
String jarPath,
|
String jarPath,
|
||||||
String network,
|
String network,
|
||||||
|
List<String> additionalNetworks,
|
||||||
Map<String, String> envVars,
|
Map<String, String> envVars,
|
||||||
Map<String, String> labels,
|
Map<String, String> labels,
|
||||||
long memoryLimitBytes,
|
long memoryLimitBytes,
|
||||||
|
Long memoryReserveBytes,
|
||||||
int cpuShares,
|
int cpuShares,
|
||||||
int healthCheckPort
|
Long cpuQuota,
|
||||||
|
List<Integer> exposedPorts,
|
||||||
|
int healthCheckPort,
|
||||||
|
String restartPolicyName,
|
||||||
|
int restartPolicyMaxRetries
|
||||||
) {}
|
) {}
|
||||||
|
|||||||
Reference in New Issue
Block a user