or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

aws-sdk-integration.mdaws-services.mdcontainer-configuration.mdendpoint-configuration.mdindex.mdnetwork-configuration.md
tile.json

network-configuration.mddocs/

Network Configuration

This document describes advanced Docker networking configurations for LocalStack, including container-to-container communication, network alias configuration, debugging, and troubleshooting.

Capabilities

Docker Network Setup

Configure LocalStack to run within a Docker network for container-to-container communication.

/**
 * Attaches the container to a Docker network
 * Enables communication between LocalStack and other containers on the same network
 * Inherited from GenericContainer
 *
 * @param network The Docker network to attach to
 * @return This container object for method chaining
 */
public LocalStackContainer withNetwork(Network network);

/**
 * Sets network aliases for the container within the Docker network
 * The last alias in the list is used as the external hostname (HOSTNAME_EXTERNAL or LOCALSTACK_HOST)
 * Inherited from GenericContainer
 *
 * @param aliases One or more network alias names
 * @return This container object for method chaining
 */
public LocalStackContainer withNetworkAliases(String... aliases);

Basic Network Configuration

Simple Network Setup

import org.testcontainers.containers.Network;
import org.testcontainers.containers.localstack.LocalStackContainer;
import org.testcontainers.containers.localstack.LocalStackContainer.Service;

// Create a Docker network
Network network = Network.newNetwork();

// Attach LocalStack to the network
LocalStackContainer localstack = new LocalStackContainer(dockerImageName)
    .withNetwork(network)
    .withNetworkAliases("localstack")
    .withServices(Service.S3, Service.SQS);

localstack.start();

// Test code running on host uses getEndpoint()
URI endpoint = localstack.getEndpoint();
System.out.println("Host endpoint: " + endpoint);
// Output: http://192.168.1.100:49153

// Containers within the network use the alias
System.out.println("Network endpoint: http://localstack:4566");

Multiple Network Aliases

Network network = Network.newNetwork();

// Set multiple aliases - the last one is used as HOSTNAME_EXTERNAL
LocalStackContainer localstack = new LocalStackContainer(dockerImageName)
    .withNetwork(network)
    .withNetworkAliases("aws", "localstack-container", "localstack")  // "localstack" is used
    .withServices(Service.S3);

localstack.start();

// All aliases can be used within the network
// http://aws:4566
// http://localstack-container:4566
// http://localstack:4566

// Verify which alias is used for HOSTNAME_EXTERNAL
String hostnameExternal = localstack.getEnvMap().get("HOSTNAME_EXTERNAL");
String localstackHost = localstack.getEnvMap().get("LOCALSTACK_HOST");
System.out.println("HOSTNAME_EXTERNAL: " + hostnameExternal);  // "localstack" (for < 2.0)
System.out.println("LOCALSTACK_HOST: " + localstackHost);  // "localstack" (for >= 2.0)

Container-to-Container Communication

Application Container Accessing LocalStack

import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Network;

Network network = Network.newNetwork();

// Start LocalStack
LocalStackContainer localstack = new LocalStackContainer(dockerImageName)
    .withNetwork(network)
    .withNetworkAliases("localstack")
    .withServices(Service.S3, Service.DYNAMODB);

localstack.start();

// Start application container on the same network
GenericContainer<?> app = new GenericContainer<>("myapp:latest")
    .withNetwork(network)
    .withEnv("AWS_ENDPOINT", "http://localstack:4566")
    .withEnv("AWS_ACCESS_KEY_ID", localstack.getAccessKey())
    .withEnv("AWS_SECRET_ACCESS_KEY", localstack.getSecretKey())
    .withEnv("AWS_REGION", localstack.getRegion())
    .withExposedPorts(8080);

app.start();

// The app container can now access LocalStack at http://localstack:4566

Multiple Application Containers

Network network = Network.newNetwork();

LocalStackContainer localstack = new LocalStackContainer(dockerImageName)
    .withNetwork(network)
    .withNetworkAliases("localstack")
    .withServices(Service.S3, Service.SQS, Service.DYNAMODB);

localstack.start();

// Frontend service
GenericContainer<?> frontend = new GenericContainer<>("frontend:latest")
    .withNetwork(network)
    .withEnv("AWS_ENDPOINT", "http://localstack:4566")
    .withEnv("AWS_REGION", localstack.getRegion())
    .withExposedPorts(3000);

// Backend service
GenericContainer<?> backend = new GenericContainer<>("backend:latest")
    .withNetwork(network)
    .withEnv("AWS_ENDPOINT", "http://localstack:4566")
    .withEnv("AWS_ACCESS_KEY_ID", localstack.getAccessKey())
    .withEnv("AWS_SECRET_ACCESS_KEY", localstack.getSecretKey())
    .withEnv("AWS_REGION", localstack.getRegion())
    .withExposedPorts(8080);

frontend.start();
backend.start();

// Both frontend and backend can access LocalStack

Testing with AWS CLI Container

Run AWS CLI commands from within the Docker network:

import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.Container.ExecResult;

Network network = Network.newNetwork();

LocalStackContainer localstack = new LocalStackContainer(dockerImageName)
    .withNetwork(network)
    .withNetworkAliases("localstack")
    .withServices(Service.S3, Service.SQS);

localstack.start();

// AWS CLI container
GenericContainer<?> awsCli = new GenericContainer<>("amazon/aws-cli:latest")
    .withNetwork(network)
    .withCreateContainerCmdModifier(cmd -> cmd.withEntrypoint("tail"))
    .withCommand("-f /dev/null")
    .withEnv("AWS_ACCESS_KEY_ID", localstack.getAccessKey())
    .withEnv("AWS_SECRET_ACCESS_KEY", localstack.getSecretKey())
    .withEnv("AWS_REGION", localstack.getRegion());

awsCli.start();

// Execute AWS CLI commands
ExecResult result = awsCli.execInContainer(
    "aws", "s3", "mb", "s3://test-bucket",
    "--endpoint-url", "http://localstack:4566"
);

System.out.println("Exit code: " + result.getExitCode());
System.out.println("Output: " + result.getStdout());

// List buckets
ExecResult listResult = awsCli.execInContainer(
    "aws", "s3", "ls",
    "--endpoint-url", "http://localstack:4566"
);

System.out.println("Buckets: " + listResult.getStdout());

Hostname Resolution

Automatic Hostname Configuration

LocalStack automatically configures the external hostname based on the network setup:

Network network = Network.newNetwork();

LocalStackContainer localstack = new LocalStackContainer(
    DockerImageName.parse("localstack/localstack:2.0")
)
    .withNetwork(network)
    .withNetworkAliases("localstack")
    .withServices(Service.SQS);

localstack.start();

// For LocalStack 2.0+, LOCALSTACK_HOST is set
String localstackHost = localstack.getEnvMap().get("LOCALSTACK_HOST");
System.out.println("LOCALSTACK_HOST: " + localstackHost);  // "localstack"

// For older versions
LocalStackContainer legacyLocalstack = new LocalStackContainer(
    DockerImageName.parse("localstack/localstack:0.12")
)
    .withNetwork(network)
    .withNetworkAliases("localstack")
    .withServices(Service.SQS);

legacyLocalstack.start();

String hostnameExternal = legacyLocalstack.getEnvMap().get("HOSTNAME_EXTERNAL");
System.out.println("HOSTNAME_EXTERNAL: " + hostnameExternal);  // "localstack"

Manual Hostname Override

Network network = Network.newNetwork();

// Override the hostname manually
LocalStackContainer localstack = new LocalStackContainer(dockerImageName)
    .withNetwork(network)
    .withNetworkAliases("myalias")
    .withEnv("LOCALSTACK_HOST", "custom-hostname")
    .withServices(Service.S3);

localstack.start();

String hostname = localstack.getEnvMap().get("LOCALSTACK_HOST");
System.out.println("Custom hostname: " + hostname);  // "custom-hostname"

SQS Queue URLs with Networks

When using SQS within a Docker network, queue URLs will contain the network alias:

import software.amazon.awssdk.services.sqs.SqsClient;

Network network = Network.newNetwork();

LocalStackContainer localstack = new LocalStackContainer(dockerImageName)
    .withNetwork(network)
    .withNetworkAliases("localstack")
    .withServices(Service.SQS);

localstack.start();

// Create SQS client (from host)
SqsClient sqs = SqsClient.builder()
    .endpointOverride(localstack.getEndpoint())
    .credentialsProvider(
        StaticCredentialsProvider.create(
            AwsBasicCredentials.create(
                localstack.getAccessKey(),
                localstack.getSecretKey()
            )
        )
    )
    .region(Region.of(localstack.getRegion()))
    .build();

// Create queue
String queueUrl = sqs.createQueue(q -> q.queueName("test-queue"))
    .queueUrl();

System.out.println("Queue URL: " + queueUrl);
// Output: http://localstack:4566/000000000000/test-queue

// The queue URL contains the network alias "localstack"
// This URL works from containers within the network

Network Bridge vs Docker Network

Bridge Network (Default)

Without specifying a network, LocalStack runs on the default bridge network and is exposed to the host:

// No network configuration - uses bridge network
LocalStackContainer localstack = new LocalStackContainer(dockerImageName)
    .withServices(Service.S3);

localstack.start();

// Access from host
URI endpoint = localstack.getEndpoint();
System.out.println("Endpoint: " + endpoint);
// Output: http://192.168.1.100:49153 (host IP and mapped port)

// Not accessible to other containers by default

Custom Docker Network

With a custom network, LocalStack can communicate with other containers:

Network network = Network.newNetwork();

LocalStackContainer localstack = new LocalStackContainer(dockerImageName)
    .withNetwork(network)
    .withNetworkAliases("localstack")
    .withServices(Service.S3);

localstack.start();

// Access from host (still uses mapped port)
URI endpoint = localstack.getEndpoint();
System.out.println("Host endpoint: " + endpoint);
// Output: http://192.168.1.100:49153

// Access from containers within the network
System.out.println("Network endpoint: http://localstack:4566");

Complete Multi-Container Example

import org.testcontainers.containers.Network;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.localstack.LocalStackContainer;
import org.testcontainers.containers.localstack.LocalStackContainer.Service;
import org.testcontainers.utility.DockerImageName;
import org.junit.jupiter.api.Test;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;

@Testcontainers
public class NetworkIntegrationTest {

    // Shared network
    private static final Network network = Network.newNetwork();

    @Container
    static LocalStackContainer localstack = new LocalStackContainer(
        DockerImageName.parse("localstack/localstack:2.0")
    )
        .withNetwork(network)
        .withNetworkAliases("localstack")
        .withServices(Service.S3, Service.SQS, Service.DYNAMODB);

    @Container
    static GenericContainer<?> app = new GenericContainer<>("myapp:latest")
        .withNetwork(network)
        .withEnv("AWS_ENDPOINT", "http://localstack:4566")
        .withEnv("AWS_ACCESS_KEY_ID", "test")
        .withEnv("AWS_SECRET_ACCESS_KEY", "test")
        .withEnv("AWS_REGION", "us-east-1")
        .withExposedPorts(8080)
        .dependsOn(localstack);

    @Test
    void testAppCanAccessLocalStack() {
        // From the test (running on host), use getEndpoint()
        S3Client s3 = S3Client.builder()
            .endpointOverride(localstack.getEndpoint())
            .credentialsProvider(
                StaticCredentialsProvider.create(
                    AwsBasicCredentials.create(
                        localstack.getAccessKey(),
                        localstack.getSecretKey()
                    )
                )
            )
            .region(Region.of(localstack.getRegion()))
            .build();

        // Create a bucket
        s3.createBucket(b -> b.bucket("test-bucket"));

        // The app container can also access this bucket at http://localstack:4566
        // Make HTTP request to app container and verify it can interact with S3
        String appUrl = "http://" + app.getHost() + ":" + app.getMappedPort(8080);
        // ... test app endpoints that use LocalStack
    }
}

Lambda and ECS Container Labels

LocalStack automatically configures Docker labels for spawned Lambda and ECS containers to ensure proper cleanup:

LocalStackContainer localstack = new LocalStackContainer(dockerImageName)
    .withServices(Service.LAMBDA);

localstack.start();

// When Lambda functions are invoked, LocalStack spawns containers
// These containers are automatically labeled with Testcontainers labels
// This ensures they are cleaned up when the LocalStack container stops

// The labels include:
// - org.testcontainers=true
// - org.testcontainers.sessionId=<session-id>
// - org.testcontainers.version=<version>

// This is handled automatically via environment variables:
// LAMBDA_DOCKER_FLAGS, ECS_DOCKER_FLAGS, EC2_DOCKER_FLAGS, BATCH_DOCKER_FLAGS

Network Cleanup

Networks are automatically cleaned up when containers stop:

Network network = Network.newNetwork();

try {
    LocalStackContainer localstack = new LocalStackContainer(dockerImageName)
        .withNetwork(network)
        .withNetworkAliases("localstack")
        .withServices(Service.S3);

    localstack.start();

    // Use LocalStack
    // ...

    localstack.stop();
} finally {
    // Clean up network
    network.close();
}

// With JUnit 5 and @Testcontainers, cleanup is automatic

Troubleshooting Network Issues

Container Cannot Reach LocalStack

Problem: Application container cannot connect to LocalStack.

Solutions:

  • Verify containers are on same network: localstack.withNetwork(network) and app.withNetwork(network)
  • Use network alias in endpoint URL: http://localstack:4566 (not getEndpoint())
  • Check network alias is set: localstack.withNetworkAliases("localstack")
  • Verify LocalStack is started before application container
  • Check network alias is last in list (used as HOSTNAME_EXTERNAL)
// CORRECT
Network network = Network.newNetwork();
LocalStackContainer localstack = new LocalStackContainer(dockerImageName)
    .withNetwork(network)
    .withNetworkAliases("localstack")  // Set alias
    .withServices(Service.S3);
localstack.start();

GenericContainer<?> app = new GenericContainer<>("myapp:latest")
    .withNetwork(network)  // Same network
    .withEnv("AWS_ENDPOINT", "http://localstack:4566");  // Use alias

Hostname Not Resolved

Problem: Network alias not resolving in containers.

Solutions:

  • Ensure network alias is set before container start
  • Verify last alias is used (check HOSTNAME_EXTERNAL or LOCALSTACK_HOST)
  • Check containers are on same network
  • Verify network is created before containers
// Verify hostname configuration
localstack.start();
String hostname = localstack.getEnvMap().get("LOCALSTACK_HOST");
System.out.println("Hostname: " + hostname);  // Should be "localstack"

Endpoint URL Issues

Problem: Using wrong endpoint format for network communication.

Solutions:

  • From host: Use localstack.getEndpoint() (returns IP address)
  • From containers: Use network alias http://localstack:4566 (not getEndpoint())
  • Do not use localhost in network endpoints
// WRONG - from container
String endpoint = localstack.getEndpoint().toString();  // IP address
app.withEnv("AWS_ENDPOINT", endpoint);  // May not work in network

// CORRECT - from container
app.withEnv("AWS_ENDPOINT", "http://localstack:4566");  // Use alias

Network Cleanup Issues

Problem: Network not cleaned up after tests.

Solutions:

  • Use JUnit @Testcontainers for automatic cleanup
  • Manually close network in finally block: network.close()
  • Ensure all containers are stopped before closing network
Network network = Network.newNetwork();
try {
    // ... use network
} finally {
    network.close();  // Clean up
}

Debugging Network Configuration

Inspect Network Configuration

Network network = Network.newNetwork();
LocalStackContainer localstack = new LocalStackContainer(dockerImageName)
    .withNetwork(network)
    .withNetworkAliases("localstack")
    .withServices(Service.S3);

localstack.start();

// Check network aliases
List<String> aliases = localstack.getNetworkAliases();
System.out.println("Network aliases: " + aliases);

// Check hostname environment variables
Map<String, String> env = localstack.getEnvMap();
System.out.println("HOSTNAME_EXTERNAL: " + env.get("HOSTNAME_EXTERNAL"));
System.out.println("LOCALSTACK_HOST: " + env.get("LOCALSTACK_HOST"));

// Check network ID
String networkId = localstack.getNetwork().getId();
System.out.println("Network ID: " + networkId);

Test Network Connectivity

// From application container, test connectivity
GenericContainer<?> app = new GenericContainer<>("curlimages/curl:latest")
    .withNetwork(network)
    .withCommand("curl", "-v", "http://localstack:4566/_localstack/health");

app.start();
String logs = app.getLogs();
System.out.println("Health check result: " + logs);

Verify Endpoint Accessibility

// From host
URI hostEndpoint = localstack.getEndpoint();
System.out.println("Host endpoint: " + hostEndpoint);

// From network (should use alias)
String networkEndpoint = "http://localstack:4566";
System.out.println("Network endpoint: " + networkEndpoint);

// Test from host
S3Client s3 = S3Client.builder()
    .endpointOverride(hostEndpoint)  // Use host endpoint
    .build();

// Test from container (would use network endpoint)
// app.withEnv("AWS_ENDPOINT", networkEndpoint);