Docker network creation and management for container communication. Networks enable containers to discover and communicate with each other using network aliases and custom DNS names, supporting complex multi-container test scenarios.
Core interface for Docker network management with automatic cleanup support.
/**
* Represents a Docker network for container communication.
* Implements AutoCloseable for automatic cleanup.
*/
public interface Network extends AutoCloseable {
/**
* Create a new network with default settings.
* Convenience method that returns Network.builder().build().
*
* @return new network instance
*/
static Network newNetwork();
/**
* Get a builder for creating networks with custom configuration.
* Note: Returns NetworkImpl.NetworkImplBuilder which is the internal implementation.
* Use the builder methods to configure and call build() to get a Network instance.
*
* @return network builder (internal implementation type exposed for builder pattern)
*/
static NetworkImpl.NetworkImplBuilder builder();
/**
* Shared network instance for reuse across containers.
* Useful when multiple test classes need to share a network.
* Cannot be closed by user code - only ResourceReaper can clean it up.
*/
Network SHARED;
/**
* Get the Docker network ID.
*
* @return network ID
*/
String getId();
/**
* Close and remove the network.
* Called automatically when using try-with-resources.
*/
@Override
void close();
}Usage Examples:
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.utility.DockerImageName;
// Create a new network
try (Network network = Network.newNetwork()) {
GenericContainer<?> database = new GenericContainer<>(DockerImageName.parse("postgres:15"))
.withNetwork(network)
.withNetworkAliases("db")
.withExposedPorts(5432);
GenericContainer<?> app = new GenericContainer<>(DockerImageName.parse("myapp:latest"))
.withNetwork(network)
.withEnv("DATABASE_HOST", "db") // Use network alias
.withEnv("DATABASE_PORT", "5432")
.withExposedPorts(8080);
database.start();
app.start();
// Containers can communicate using network aliases
// app can reach database at "db:5432"
} // Network automatically cleaned up
// Use shared network
GenericContainer<?> redis = new GenericContainer<>(DockerImageName.parse("redis:7.0"))
.withNetwork(Network.SHARED)
.withNetworkAliases("cache");Builder for creating networks with custom configuration. This builder is generated by Lombok's @Builder annotation and follows Lombok naming conventions.
/**
* Builder for creating custom Network instances with specific configuration.
* Generated by Lombok @Builder annotation. Method names follow Lombok conventions
* (field name without "with" prefix).
*/
public static class NetworkImplBuilder {
/**
* Set the network driver (e.g., "bridge", "overlay", "host").
* Default: "bridge"
*
* @param driver Network driver name
* @return Builder instance for chaining
*/
public NetworkImplBuilder driver(String driver);
/**
* Enable or disable IPv6 for the network.
* Default: null (Docker daemon default, typically disabled)
*
* @param enableIpv6 Boolean value - true to enable IPv6, false to disable, null for default
* @return Builder instance for chaining
*/
public NetworkImplBuilder enableIpv6(Boolean enableIpv6);
/**
* Add a single custom modifier for the CreateNetworkCmd. Allows advanced network configuration
* including labels, options, IPAM settings, and other Docker network settings.
*
* Can be called multiple times to add multiple modifiers (Lombok @Singular generates this method).
*
* Example usage for adding labels:
* .createNetworkCmdModifier(cmd -> cmd.withLabels(Map.of("env", "test")))
*
* @param createNetworkCmdModifier Consumer that modifies CreateNetworkCmd
* @return Builder instance for chaining
*/
public NetworkImplBuilder createNetworkCmdModifier(Consumer<CreateNetworkCmd> createNetworkCmdModifier);
/**
* Add multiple custom modifiers for the CreateNetworkCmd at once.
* Lombok @Singular annotation generates this plural form method.
*
* @param createNetworkCmdModifiers Collection of Consumers that modify CreateNetworkCmd
* @return Builder instance for chaining
*/
public NetworkImplBuilder createNetworkCmdModifiers(Collection<? extends Consumer<CreateNetworkCmd>> createNetworkCmdModifiers);
/**
* Build the Network instance with configured settings.
*
* @return Configured NetworkImpl instance
*/
public NetworkImpl build();
}
/**
* Implementation of Network interface. Uses Lombok @Getter annotation.
* Fields have automatically generated getter methods.
* Constructor is package-private/internal. Use Network.builder() to create instances.
*/
@Builder
@Getter
class NetworkImpl implements Network {
/**
* Get the network name (randomly generated UUID).
*
* @return network name
*/
public String getName();
/**
* Get the network ID (lazily initialized on first call).
* First call triggers network creation in Docker.
* Subsequent calls return the cached ID.
*
* @return network ID
*/
@Override
public String getId();
/**
* Get the IPv6 setting for this network.
* Lombok @Getter generates this method.
*
* @return Boolean value - true if IPv6 enabled, false if disabled, null if using default
*/
public Boolean getEnableIpv6();
/**
* Get the network driver.
* Lombok @Getter generates this method.
*
* @return network driver name (e.g., "bridge", "overlay")
*/
public String getDriver();
/**
* Get the collection of CreateNetworkCmd modifiers.
* Lombok @Getter generates this method.
*
* @return set of modifiers for custom network configuration
*/
public Set<Consumer<CreateNetworkCmd>> getCreateNetworkCmdModifiers();
/**
* Close and remove the network.
*/
@Override
public void close();
}Usage Examples:
import org.testcontainers.containers.Network;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.utility.DockerImageName;
// Create basic network using builder
Network network = Network.builder().build();
// Use the network
try (network) {
GenericContainer<?> container = new GenericContainer<>(DockerImageName.parse("alpine:latest"))
.withNetwork(network)
.withCommand("sleep", "infinity");
container.start();
} // Network cleaned up automatically
// Note: For most use cases, Network.newNetwork() is simpler and recommended
Network simpleNetwork = Network.newNetwork();Network aliases provide DNS names for containers within a network, enabling service discovery.
/**
* Set network aliases for the container.
* These become DNS names that other containers can use to reach this container.
*
* Part of GenericContainer API:
*/
public SELF withNetworkAliases(String... aliases);Usage Example:
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.utility.DockerImageName;
Network network = Network.newNetwork();
// Database with multiple aliases
GenericContainer<?> database = new GenericContainer<>(DockerImageName.parse("postgres:15"))
.withNetwork(network)
.withNetworkAliases("db", "database", "postgres") // Multiple DNS names
.withEnv("POSTGRES_PASSWORD", "secret")
.withExposedPorts(5432);
// Cache with alias
GenericContainer<?> redis = new GenericContainer<>(DockerImageName.parse("redis:7.0"))
.withNetwork(network)
.withNetworkAliases("cache", "redis")
.withExposedPorts(6379);
// Application can reach services using any of their aliases
GenericContainer<?> app = new GenericContainer<>(DockerImageName.parse("myapp:latest"))
.withNetwork(network)
.withEnv("DATABASE_URL", "postgresql://postgres:5432/test") // Using alias
.withEnv("REDIS_URL", "redis://cache:6379") // Using alias
.withExposedPorts(8080);
database.start();
redis.start();
app.start();
// Inside the app container:
// - "db", "database", or "postgres" all resolve to the database container
// - "cache" or "redis" resolve to the Redis containerAlternative to custom networks - use predefined network modes.
/**
* Set the network mode for the container.
* Alternative to using Network objects.
*
* Part of GenericContainer API:
*/
public SELF withNetworkMode(String networkMode);Network Mode Values:
"bridge" - Default bridge network"host" - Use host network (container shares host's network stack)"none" - No network"container:<name|id>" - Share another container's network"<network-name>" - Connect to named networkUsage Examples:
// Use host network
GenericContainer<?> hostNetwork = new GenericContainer<>(DockerImageName.parse("nginx:alpine"))
.withNetworkMode("host"); // Container uses host's network directly
// Use bridge network (default)
GenericContainer<?> bridgeNetwork = new GenericContainer<>(DockerImageName.parse("redis:7.0"))
.withNetworkMode("bridge");
// Share another container's network
GenericContainer<?> sidecar = new GenericContainer<>(DockerImageName.parse("alpine:latest"))
.withNetworkMode("container:" + mainContainer.getContainerId());
// Connect to existing network by name
GenericContainer<?> existing = new GenericContainer<>(DockerImageName.parse("postgres:15"))
.withNetworkMode("my-existing-network");import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.containers.wait.strategy.Wait;
import org.testcontainers.utility.DockerImageName;
import java.time.Duration;
public class MultiContainerNetworkTest {
@Test
public void testApplicationWithDependencies() {
// Create shared network
try (Network network = Network.newNetwork()) {
// PostgreSQL database
GenericContainer<?> postgres = new GenericContainer<>(
DockerImageName.parse("postgres:15"))
.withNetwork(network)
.withNetworkAliases("postgres", "db")
.withEnv("POSTGRES_DB", "appdb")
.withEnv("POSTGRES_USER", "appuser")
.withEnv("POSTGRES_PASSWORD", "secret")
.withExposedPorts(5432)
.waitingFor(Wait.forListeningPort()
.withStartupTimeout(Duration.ofSeconds(60)));
// Redis cache
GenericContainer<?> redis = new GenericContainer<>(
DockerImageName.parse("redis:7.0-alpine"))
.withNetwork(network)
.withNetworkAliases("redis", "cache")
.withExposedPorts(6379)
.waitingFor(Wait.forListeningPort());
// RabbitMQ message broker
GenericContainer<?> rabbitmq = new GenericContainer<>(
DockerImageName.parse("rabbitmq:3-management-alpine"))
.withNetwork(network)
.withNetworkAliases("rabbitmq", "mq")
.withExposedPorts(5672, 15672)
.waitingFor(Wait.forListeningPort());
// Application container
GenericContainer<?> app = new GenericContainer<>(
DockerImageName.parse("myapp:latest"))
.withNetwork(network)
.withNetworkAliases("app")
.withEnv("DATABASE_URL", "postgresql://appuser:secret@postgres:5432/appdb")
.withEnv("REDIS_URL", "redis://cache:6379")
.withEnv("RABBITMQ_URL", "amqp://rabbitmq:5672")
.withExposedPorts(8080)
.dependsOn(postgres, redis, rabbitmq)
.waitingFor(Wait.forHttp("/health")
.forStatusCode(200)
.withStartupTimeout(Duration.ofMinutes(2)));
// Start all containers (dependencies start automatically)
app.start();
// All containers can communicate using their network aliases
String appUrl = String.format("http://%s:%d",
app.getHost(), app.getMappedPort(8080));
// Run tests against the application
// ...
} // Network and all containers cleaned up automatically
}
}import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.lifecycle.Startables;
import org.testcontainers.utility.DockerImageName;
public class MicroservicesTest {
@Test
public void testMicroservicesCommunication() {
Network network = Network.newNetwork();
// Service registry
GenericContainer<?> consul = new GenericContainer<>(
DockerImageName.parse("consul:1.15"))
.withNetwork(network)
.withNetworkAliases("consul", "service-registry")
.withExposedPorts(8500);
// User service
GenericContainer<?> userService = new GenericContainer<>(
DockerImageName.parse("user-service:latest"))
.withNetwork(network)
.withNetworkAliases("user-service")
.withEnv("CONSUL_URL", "http://consul:8500")
.withExposedPorts(8081)
.dependsOn(consul);
// Order service
GenericContainer<?> orderService = new GenericContainer<>(
DockerImageName.parse("order-service:latest"))
.withNetwork(network)
.withNetworkAliases("order-service")
.withEnv("CONSUL_URL", "http://consul:8500")
.withEnv("USER_SERVICE_URL", "http://user-service:8081")
.withExposedPorts(8082)
.dependsOn(consul, userService);
// API Gateway
GenericContainer<?> gateway = new GenericContainer<>(
DockerImageName.parse("api-gateway:latest"))
.withNetwork(network)
.withNetworkAliases("gateway")
.withEnv("CONSUL_URL", "http://consul:8500")
.withExposedPorts(8080)
.dependsOn(consul, userService, orderService);
// Start all services
Startables.deepStart(gateway).join();
// Services can discover each other via Consul
// Order service can call user service using network alias
String gatewayUrl = String.format("http://%s:%d",
gateway.getHost(), gateway.getMappedPort(8080));
// Test API calls through gateway
}
}import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.utility.DockerImageName;
// Shared infrastructure for all tests
public class TestInfrastructure {
// Shared network used by all test classes
public static final Network SHARED_NETWORK = Network.SHARED;
// Shared database for all tests
public static final GenericContainer<?> POSTGRES = new GenericContainer<>(
DockerImageName.parse("postgres:15"))
.withNetwork(SHARED_NETWORK)
.withNetworkAliases("shared-db")
.withEnv("POSTGRES_PASSWORD", "test")
.withExposedPorts(5432);
static {
POSTGRES.start();
}
}
// Test class 1
public class UserServiceTest {
@Test
public void testUserService() {
GenericContainer<?> userService = new GenericContainer<>(
DockerImageName.parse("user-service:latest"))
.withNetwork(TestInfrastructure.SHARED_NETWORK)
.withEnv("DB_HOST", "shared-db")
.withExposedPorts(8081);
userService.start();
// Test uses shared database
}
}
// Test class 2
public class OrderServiceTest {
@Test
public void testOrderService() {
GenericContainer<?> orderService = new GenericContainer<>(
DockerImageName.parse("order-service:latest"))
.withNetwork(TestInfrastructure.SHARED_NETWORK)
.withEnv("DB_HOST", "shared-db")
.withExposedPorts(8082);
orderService.start();
// Test also uses shared database
}
}Advanced network configuration using the builder with custom modifiers.
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.utility.DockerImageName;
import com.github.dockerjava.api.command.CreateNetworkCmd;
import java.util.Map;
public class CustomNetworkTest {
@Test
public void testWithCustomNetworkSettings() {
// Create network with custom driver
Network customNetwork = Network.builder()
.driver("bridge")
.enableIpv6(false)
.build();
try (Network network = customNetwork) {
GenericContainer<?> container1 = new GenericContainer<>(
DockerImageName.parse("alpine:latest"))
.withNetwork(network)
.withNetworkAliases("service-a")
.withCommand("sleep", "infinity");
GenericContainer<?> container2 = new GenericContainer<>(
DockerImageName.parse("alpine:latest"))
.withNetwork(network)
.withNetworkAliases("service-b")
.withCommand("sleep", "infinity");
container1.start();
container2.start();
// Test network connectivity
Container.ExecResult result = container1.execInContainer(
"ping", "-c", "1", "service-b");
assertEquals(0, result.getExitCode());
}
}
@Test
public void testWithAdvancedNetworkSettings() {
// Use createNetworkCmdModifier for advanced configuration like labels and options
Network advancedNetwork = Network.builder()
.driver("bridge")
.createNetworkCmdModifier(cmd -> {
// Add custom labels
cmd.withLabels(Map.of(
"test.suite", "integration",
"test.environment", "custom"
));
})
.createNetworkCmdModifier(cmd -> {
// Add custom options (MTU, bridge name, etc.)
cmd.withOptions(Map.of(
"com.docker.network.bridge.name", "testcontainers-custom",
"com.docker.network.driver.mtu", "1450"
));
})
.build();
try (Network network = advancedNetwork) {
GenericContainer<?> container = new GenericContainer<>(
DockerImageName.parse("alpine:latest"))
.withNetwork(network)
.withCommand("sleep", "infinity");
container.start();
// Network has custom labels and options applied
}
}
@Test
public void testWithIPAMConfiguration() {
// Configure custom IP Address Management (IPAM) settings
Network ipamNetwork = Network.builder()
.driver("bridge")
.createNetworkCmdModifier(cmd -> {
// Configure IPAM with custom subnet and gateway
cmd.withIpamConfig(
// IPAM configuration with specific subnet and gateway
new IPAM()
.withDriver("default")
.withConfig(new IPAMConfig()
.withSubnet("172.20.0.0/16")
.withGateway("172.20.0.1")
)
);
})
.build();
try (Network network = ipamNetwork) {
// Containers in this network use the custom subnet
GenericContainer<?> db = new GenericContainer<>(
DockerImageName.parse("postgres:15"))
.withNetwork(network)
.withNetworkAliases("database");
db.start();
// Database is on 172.20.0.0/16 subnet
}
}
@Test
public void testWithEnableIPv6() {
// Enable IPv6 on the network
Network ipv6Network = Network.builder()
.driver("bridge")
.enableIpv6(true)
.createNetworkCmdModifier(cmd -> {
// Configure IPv6 CIDR
cmd.withIpamConfig(
new IPAM()
.withDriver("default")
.withConfig(new IPAMConfig()
.withSubnet("2001:db8::/32")
)
);
})
.build();
try (Network network = ipv6Network) {
GenericContainer<?> container = new GenericContainer<>(
DockerImageName.parse("alpine:latest"))
.withNetwork(network)
.withCommand("sleep", "infinity");
container.start();
// Container has both IPv4 and IPv6 addresses
}
}
}Use custom networks when:
Use network modes when:
// Always use try-with-resources for automatic cleanup
try (Network network = Network.newNetwork()) {
// Use network
} // Automatically cleaned up
// Or manually manage lifecycle
Network network = Network.newNetwork();
try {
// Use network
} finally {
network.close();
}// Create separate networks for isolation
public class IsolatedNetworkTest {
@Test
public void testServiceIsolation() {
// Network A - Services that should communicate
try (Network networkA = Network.newNetwork()) {
GenericContainer<?> serviceA1 = createService(networkA, "service-a1");
GenericContainer<?> serviceA2 = createService(networkA, "service-a2");
// Network B - Isolated services
try (Network networkB = Network.newNetwork()) {
GenericContainer<?> serviceB1 = createService(networkB, "service-b1");
GenericContainer<?> serviceB2 = createService(networkB, "service-b2");
// Services in A can communicate with each other
// Services in B can communicate with each other
// Services in A cannot reach services in B (and vice versa)
}
}
}
}Complete API reference for network-related methods in GenericContainer.
/**
* Network configuration methods in GenericContainer.
*/
public class GenericContainer<SELF extends GenericContainer<SELF>> {
/**
* Set the network for this container.
*
* @param network the network to use
* @return this container for method chaining
*/
public SELF withNetwork(Network network);
/**
* Get the network for this container.
*
* @return the network, or null if not set
*/
public Network getNetwork();
/**
* Set the network for this container.
*
* @param network the network to use
*/
public void setNetwork(Network network);
/**
* Set the network mode for this container.
*
* @param networkMode the network mode (e.g., "bridge", "host", "none", or "container:<name|id>")
* @return this container for method chaining
*/
public SELF withNetworkMode(String networkMode);
/**
* Get the network mode for this container.
*
* @return the network mode string
*/
public String getNetworkMode();
/**
* Set the network mode for this container.
*
* @param networkMode the network mode to use
*/
public void setNetworkMode(String networkMode);
/**
* Set network aliases for this container.
* These become DNS names that other containers on the same network can use.
*
* @param aliases one or more network aliases
* @return this container for method chaining
*/
public SELF withNetworkAliases(String... aliases);
/**
* Get the network aliases for this container.
*
* @return list of network aliases
*/
public List<String> getNetworkAliases();
/**
* Set the network aliases for this container.
*
* @param aliases list of network aliases
*/
public void setNetworkAliases(List<String> aliases);
}