Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,12 @@ public record DockerConfiguration(
@Nullable String registryPassword,
@Nullable String registryUrl,
@Nullable String user,
@Nullable HostAndPort nodeHostOverride
@Nullable HostAndPort nodeHostOverride,
@Nullable String portBindAddress
) {

public static final String AUTO_PORT_BIND_ADDRESS = "auto";

public static @NonNull Builder builder() {
return new Builder();
}
Expand All @@ -59,7 +62,9 @@ public record DockerConfiguration(
.registryEmail(configuration.registryEmail())
.registryPassword(configuration.registryPassword())
.registryUrl(configuration.registryUrl())
.user(configuration.user());
.user(configuration.user())
.nodeHostOverride(configuration.nodeHostOverride())
.portBindAddress(configuration.portBindAddress());
}

public static final class Builder {
Expand All @@ -82,6 +87,7 @@ public static final class Builder {

private String user;
private HostAndPort nodeHostOverride;
private String portBindAddress;

public @NonNull Builder javaImage(@NonNull DockerImage javaImage) {
this.javaImage = javaImage;
Expand Down Expand Up @@ -168,6 +174,11 @@ public static final class Builder {
return this;
}

public @NonNull Builder portBindAddress(@Nullable String portBindAddress) {
this.portBindAddress = portBindAddress;
return this;
}

public @NonNull DockerConfiguration build() {
Preconditions.checkNotNull(this.javaImage, "Java docker image must be given");
return new DockerConfiguration(
Expand All @@ -184,7 +195,8 @@ public static final class Builder {
this.registryPassword,
this.registryUrl,
this.user,
this.nodeHostOverride);
this.nodeHostOverride,
this.portBindAddress);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import com.github.dockerjava.api.model.HostConfig;
import com.github.dockerjava.api.model.InternetProtocol;
import com.github.dockerjava.api.model.LogConfig;
import com.github.dockerjava.api.model.Ports;
import com.github.dockerjava.api.model.RestartPolicy;
import com.github.dockerjava.api.model.Volume;
import eu.cloudnetservice.driver.document.property.DocProperty;
Expand All @@ -54,6 +55,8 @@
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.Collection;
Expand Down Expand Up @@ -229,6 +232,36 @@ protected void doStartProcess(
// an isolated, single java installation available which is always accessible via 'java'
arguments.set(0, "java");

// build host configuration
var hostConfig = HostConfig.newHostConfig()
.withBinds(binds)
.withCapDrop(DROPPED_CAPABILITIES)
.withRestartPolicy(RestartPolicy.noRestart())
.withNetworkMode(this.configuration.network())
.withLogConfig(new LogConfig(LogConfig.LoggingType.LOCAL, LOGGING_OPTIONS));

// add port bindings if configured and not using host network mode
var portBindAddress = this.configuration.portBindAddress();
if (portBindAddress != null && !"host".equals(this.configuration.network())) {
var servicePort = this.serviceConfiguration.port();

// resolve the bind address if it's set to "auto" (uses hostAddress)
String resolvedBindAddress;
if (DockerConfiguration.AUTO_PORT_BIND_ADDRESS.equals(portBindAddress)) {
resolvedBindAddress = this.resolveHostAddress(this.serviceConfiguration.hostAddress());
} else {
resolvedBindAddress = portBindAddress;
}

// only add port bindings if we have a valid bind address
if (resolvedBindAddress != null) {
var portBindings = new Ports();
portBindings.bind(ExposedPort.tcp(servicePort), Ports.Binding.bindIpAndPort(resolvedBindAddress, servicePort));
portBindings.bind(ExposedPort.udp(servicePort), Ports.Binding.bindIpAndPort(resolvedBindAddress, servicePort));
hostConfig.withPortBindings(portBindings);
}
}

// create the container and store the container id
this.containerId = this.dockerClient.createContainerCmd(image.imageName())
.withEnv(env)
Expand All @@ -243,12 +276,7 @@ protected void doStartProcess(
.withExposedPorts(exposedPorts)
.withName(this.serviceId().name() + "_" + this.serviceId().uniqueId())
.withWorkingDir(this.serviceDirectory.toAbsolutePath().toString())
.withHostConfig(HostConfig.newHostConfig()
.withBinds(binds)
.withCapDrop(DROPPED_CAPABILITIES)
.withRestartPolicy(RestartPolicy.noRestart())
.withNetworkMode(this.configuration.network())
.withLogConfig(new LogConfig(LogConfig.LoggingType.LOCAL, LOGGING_OPTIONS)))
.withHostConfig(hostConfig)
.withLabels(Map.of(
"Service", "CloudNet",
"Name", this.serviceId().name(),
Expand Down Expand Up @@ -402,6 +430,22 @@ protected boolean needsImagePull(@NonNull DockerImage image) {
return new Bind(path, new Volume(path), accessMode);
}

protected @Nullable String resolveHostAddress(@NonNull String hostAddress) {
try {
var inetAddress = InetAddress.getByName(hostAddress);
var resolvedAddress = inetAddress.getHostAddress();
// remove IPv6 scope identifier if present (e.g., fe80::1%eth0 -> fe80::1)
var scopeIndex = resolvedAddress.indexOf('%');
if (scopeIndex != -1) {
resolvedAddress = resolvedAddress.substring(0, scopeIndex);
}
return resolvedAddress;
} catch (UnknownHostException exception) {
LOGGER.warn("Unable to resolve host address {} for port binding", hostAddress, exception);
return null;
}
}

public final class ServiceLogCacheAdapter extends ResultCallback.Adapter<Frame> {

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public void loadConfiguration() {
null,
null,
null,
null,
null),
DocumentFactory.json());
}
Expand Down
Loading