or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

configuration.mdcontainer-lifecycle.mddocker-client.mddocker-compose.mdimage-building.mdimage-management.mdimage-pull-policies.mdindex.mdjunit-jupiter-integration.mdlifecycle.mdmodules-overview.mdnetwork-configuration.mdoutput-handling.mdstartup-checks.mdutility-classes.mdwait-strategies.md
tile.json

network-configuration.mddocs/

Network Configuration

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.

Capabilities

Network Interface

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");

NetworkImpl.NetworkImplBuilder

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

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 container

Network Modes

Alternative 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 network

Usage 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");

Complete Usage Examples

Multi-Container Application with Service Discovery

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
    }
}

Microservices Communication Test

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
    }
}

Shared Network Across Test Classes

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
    }
}

Custom Network Configuration

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
        }
    }
}

Best Practices

When to Use Networks

Use custom networks when:

  • Multiple containers need to communicate
  • Containers need to discover each other by name
  • Testing microservices or distributed systems
  • Isolating test environments

Use network modes when:

  • Testing host networking requirements
  • Container needs direct host network access
  • Sharing network namespace with another container

Network Cleanup

// 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();
}

Network Isolation

// 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)
            }
        }
    }
}

API Reference

GenericContainer Network Methods

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);
}