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

container-configuration.mddocs/

Container Configuration

This document describes how to create and configure LocalStack containers, including service selection, environment variables, Docker settings, troubleshooting, and common pitfalls.

Capabilities

Container Construction

Creates a LocalStack container instance with a specified Docker image.

/**
 * Creates a LocalStack container with the specified Docker image
 * The constructor automatically detects the LocalStack version and configures
 * legacy mode, services requirements, and environment variables accordingly
 *
 * @param dockerImageName Docker image name for LocalStack (e.g., "localstack/localstack:2.0")
 * @throws IllegalArgumentException if image is not compatible with localstack/localstack or localstack/localstack-pro
 */
public LocalStackContainer(DockerImageName dockerImageName);

Usage Examples:

import org.testcontainers.containers.localstack.LocalStackContainer;
import org.testcontainers.utility.DockerImageName;

// Use latest version
LocalStackContainer localstack = new LocalStackContainer(
    DockerImageName.parse("localstack/localstack:latest")
);

// Use specific version
LocalStackContainer localstack = new LocalStackContainer(
    DockerImageName.parse("localstack/localstack:2.0")
);

// Use LocalStack Pro
LocalStackContainer localstackPro = new LocalStackContainer(
    DockerImageName.parse("localstack/localstack-pro:2.0")
);

Service Configuration

Declares which AWS services should be launched by the LocalStack container.

/**
 * Declares AWS services to be launched by the container using predefined Service enum values
 * For versions < 0.13, at least one service must be specified
 * For versions >= 0.13, services are optional and start lazily
 *
 * @param services One or more Service enum values (e.g., Service.S3, Service.SQS)
 * @return This container object for method chaining
 */
public LocalStackContainer withServices(Service... services);

/**
 * Declares AWS services using the EnabledService interface
 * This method allows specifying custom service names not in the Service enum
 *
 * @param services One or more EnabledService implementations
 * @return This container object for method chaining
 */
public LocalStackContainer withServices(EnabledService... services);

Usage Examples:

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

// Configure with predefined services
LocalStackContainer localstack = new LocalStackContainer(dockerImageName)
    .withServices(Service.S3, Service.SQS, Service.LAMBDA);

// Mix predefined and custom services
LocalStackContainer localstack = new LocalStackContainer(dockerImageName)
    .withServices(
        Service.S3,
        Service.DYNAMODB,
        EnabledService.named("events"),  // Custom service name
        EnabledService.named("stepfunctions")
    );

// No services specified (versions >= 0.13 only)
// Services will start lazily when first accessed
LocalStackContainer localstack = new LocalStackContainer(
    DockerImageName.parse("localstack/localstack:2.0")
);

Environment Variable Configuration

Configure LocalStack behavior using environment variables.

/**
 * Sets an environment variable for the container
 * Inherited from GenericContainer
 *
 * @param key Environment variable name
 * @param value Environment variable value
 * @return This container object for method chaining
 */
public LocalStackContainer withEnv(String key, String value);

Common Environment Variables:

  • DEFAULT_REGION: AWS region (default: "us-east-1")
  • AWS_ACCESS_KEY_ID: AWS access key (default: "test")
  • AWS_SECRET_ACCESS_KEY: AWS secret key (default: "test")
  • S3_SKIP_SIGNATURE_VALIDATION: Skip S3 signature validation ("0" or "1")
  • LAMBDA_DOCKER_FLAGS: Additional Docker flags for Lambda containers
  • ECS_DOCKER_FLAGS: Additional Docker flags for ECS containers
  • EAGER_SERVICE_LOADING: Force eager service loading (auto-configured)
  • HOSTNAME_EXTERNAL or LOCALSTACK_HOST: External hostname (auto-configured)
  • LOCALSTACK_API_KEY: API key for LocalStack Pro features
  • DEBUG: Enable debug logging ("1" to enable)
  • DATA_DIR: Directory for persistent data (requires volume mount)

Usage Examples:

// Custom region
LocalStackContainer localstack = new LocalStackContainer(dockerImageName)
    .withEnv("DEFAULT_REGION", "eu-west-1")
    .withServices(Service.S3);

// Custom credentials
LocalStackContainer localstack = new LocalStackContainer(dockerImageName)
    .withEnv("AWS_ACCESS_KEY_ID", "mykey")
    .withEnv("AWS_SECRET_ACCESS_KEY", "mysecret")
    .withServices(Service.S3, Service.DYNAMODB);

// Skip S3 signature validation
LocalStackContainer localstack = new LocalStackContainer(dockerImageName)
    .withEnv("S3_SKIP_SIGNATURE_VALIDATION", "1")
    .withServices(Service.S3);

// Enable debug logging
LocalStackContainer localstack = new LocalStackContainer(dockerImageName)
    .withEnv("DEBUG", "1")
    .withServices(Service.S3);

// LocalStack Pro
LocalStackContainer localstackPro = new LocalStackContainer(
    DockerImageName.parse("localstack/localstack-pro:2.0")
)
    .withEnv("LOCALSTACK_API_KEY", System.getenv("LOCALSTACK_API_KEY"))
    .withServices(Service.S3);

Network Configuration

Configure Docker networking for the container.

/**
 * Attaches the container to a Docker 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 is used as the external hostname for LocalStack
 * Inherited from GenericContainer
 *
 * @param aliases One or more network alias names
 * @return This container object for method chaining
 */
public LocalStackContainer withNetworkAliases(String... aliases);

Usage Examples:

import org.testcontainers.containers.Network;

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

// Attach LocalStack to the network with an alias
LocalStackContainer localstack = new LocalStackContainer(dockerImageName)
    .withNetwork(network)
    .withNetworkAliases("localstack")  // Last alias used as HOSTNAME_EXTERNAL
    .withServices(Service.S3, Service.SQS);

// Multiple containers on the same network
GenericContainer<?> appContainer = new GenericContainer<>("myapp:latest")
    .withNetwork(network)
    .withEnv("AWS_ENDPOINT", "http://localstack:4566");

Container Lifecycle

Start and stop the container.

/**
 * Starts the LocalStack container
 * Inherited from GenericContainer
 * Waits for the "Ready." log message before returning
 */
public void start();

/**
 * Stops the LocalStack container
 * Inherited from GenericContainer
 */
public void stop();

Usage Examples:

// Manual lifecycle management
LocalStackContainer localstack = new LocalStackContainer(dockerImageName)
    .withServices(Service.S3);

localstack.start();
try {
    // Use the container
    URI endpoint = localstack.getEndpoint();
    // ... perform tests
} finally {
    localstack.stop();
}

// JUnit 4 integration with @ClassRule (automatic lifecycle)
import org.junit.ClassRule;

public class MyTest {
    @ClassRule
    public static LocalStackContainer localstack = new LocalStackContainer(dockerImageName)
        .withServices(Service.S3);

    @Test
    public void testSomething() {
        // Container automatically started before test and stopped after
    }
}

// JUnit 5 integration with @Testcontainers (automatic lifecycle)
import org.junit.jupiter.api.Test;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;

@Testcontainers
public class MyTest {
    @Container
    static LocalStackContainer localstack = new LocalStackContainer(dockerImageName)
        .withServices(Service.S3);

    @Test
    void testSomething() {
        // Container automatically started before test and stopped after
    }
}

Legacy Mode Configuration

For LocalStack versions prior to 0.11, legacy mode runs each service on a different port.

/**
 * Creates a LocalStack container with explicit legacy mode control
 *
 * @param dockerImageName Docker image name for LocalStack
 * @param useLegacyMode If true, each AWS service is exposed on a different port
 * @deprecated Use LocalStackContainer(DockerImageName) instead - legacy mode is auto-detected
 */
@Deprecated
public LocalStackContainer(DockerImageName dockerImageName, boolean useLegacyMode);

/**
 * Determines if LocalStack should run in legacy mode based on version
 * Returns true for versions < 0.11, false otherwise
 *
 * @param version The LocalStack version string
 * @return true if legacy mode should be used, false otherwise
 */
static boolean shouldRunInLegacyMode(String version);

Usage Examples:

// Auto-detection (recommended)
LocalStackContainer localstack = new LocalStackContainer(
    DockerImageName.parse("localstack/localstack:0.10.7")
);
// Legacy mode automatically enabled for version 0.10.7

// Explicit control (deprecated, but still available)
LocalStackContainer localstack = new LocalStackContainer(
    DockerImageName.parse("localstack/localstack:0.11.0"),
    true  // Force legacy mode even though version supports single-port
);

Version-Specific Behavior

The LocalStackContainer automatically adapts its configuration based on the Docker image version:

Version Detection

// Version < 0.11: Legacy mode enabled
LocalStackContainer localstack = new LocalStackContainer(
    DockerImageName.parse("localstack/localstack:0.10.7")
);
// - Each service on different port
// - Services list required
// - Uses HOSTNAME_EXTERNAL

// Version >= 0.11 and < 0.13: Single-port mode, services required
LocalStackContainer localstack = new LocalStackContainer(
    DockerImageName.parse("localstack/localstack:0.11.2")
);
// - All services on port 4566
// - Services list required
// - Uses HOSTNAME_EXTERNAL

// Version >= 0.13 and < 2.0: Single-port mode, lazy loading
LocalStackContainer localstack = new LocalStackContainer(
    DockerImageName.parse("localstack/localstack:0.13.0")
);
// - All services on port 4566
// - Services list optional (lazy loading)
// - Uses HOSTNAME_EXTERNAL

// Version >= 2.0: Modern mode
LocalStackContainer localstack = new LocalStackContainer(
    DockerImageName.parse("localstack/localstack:2.0")
);
// - All services on port 4566
// - Services list optional (lazy loading)
// - Uses LOCALSTACK_HOST

// "latest" tag: Assumes latest features
LocalStackContainer localstack = new LocalStackContainer(
    DockerImageName.parse("localstack/localstack:latest")
);
// - Single-port mode
// - Lazy loading
// - LOCALSTACK_HOST

Constants

/**
 * The default LocalStack edge service port
 */
public static final int PORT = 4566;

/**
 * Default LocalStack version tag
 * @deprecated Not recommended for production use
 */
@Deprecated
public static final String VERSION = "0.11.2";

Troubleshooting

Container Startup Failures

Problem: Container fails to start with timeout error.

Solutions:

  • Increase startup timeout: localstack.withStartupTimeout(Duration.ofMinutes(5))
  • Check Docker is running: docker ps
  • Check image exists: docker images | grep localstack
  • Check logs: localstack.getLogs() or docker logs <container-id>
  • Verify Docker resources: Ensure sufficient memory and disk space
LocalStackContainer localstack = new LocalStackContainer(dockerImageName)
    .withServices(Service.S3)
    .withStartupTimeout(Duration.ofMinutes(5));  // Increase timeout

Problem: Image pull fails.

Solutions:

  • Check network connectivity
  • Verify image tag exists: docker pull localstack/localstack:2.0
  • Use specific version instead of latest
  • Check Docker registry access

Problem: Container starts but services not available.

Solutions:

  • Wait for "Ready." log message (automatic)
  • Check service is enabled: localstack.withServices(Service.S3)
  • For versions < 0.13, services must be specified
  • Check container logs for errors

Service Configuration Issues

Problem: Service not found error when calling API.

Solutions:

  • Verify service is enabled: localstack.withServices(Service.S3)
  • For versions >= 0.13, service may start lazily (first call may be slow)
  • Check service name is correct: Service.S3.getName() returns "s3"
  • For custom services, verify name matches LocalStack service name

Problem: Multiple services, some not working.

Solutions:

  • Enable all required services: localstack.withServices(Service.S3, Service.SQS)
  • Check service dependencies (e.g., DynamoDB Streams requires both Service.DYNAMODB and Service.DYNAMODB_STREAMS)
  • Verify LocalStack version supports all services

Network Issues

Problem: Cannot connect to LocalStack from test code.

Solutions:

  • Ensure container is started: localstack.start()
  • Use localstack.getEndpoint() to get correct endpoint
  • Verify endpoint is IP address (not hostname) for S3 path-style access
  • Check port mapping: localstack.getMappedPort(4566)

Problem: Cannot connect from Docker network.

Solutions:

  • Use network alias in endpoint URL: http://localstack:4566
  • Verify network alias is set: localstack.withNetworkAliases("localstack")
  • Check container is on same network: localstack.withNetwork(network)
  • Verify network alias is last in list (used as HOSTNAME_EXTERNAL)

Credential Issues

Problem: Authentication errors from AWS SDK.

Solutions:

  • Use default credentials: localstack.getAccessKey() and localstack.getSecretKey()
  • Verify credentials provider is configured correctly
  • Check environment variables if custom credentials used
  • Ensure credentials are retrieved after start() is called

Version Compatibility Issues

Problem: Behavior differs from expected (legacy vs modern mode).

Solutions:

  • Check LocalStack version: Use explicit version tag
  • Verify version detection: Legacy mode auto-detected for < 0.11
  • Use getEndpointOverride(Service) for legacy mode service-specific endpoints
  • Check version-specific requirements (e.g., services list requirement)

Common Pitfalls

Forgetting to Start Container

// WRONG - will throw IllegalStateException
LocalStackContainer localstack = new LocalStackContainer(dockerImageName)
    .withServices(Service.S3);
URI endpoint = localstack.getEndpoint();  // IllegalStateException!

// CORRECT
LocalStackContainer localstack = new LocalStackContainer(dockerImageName)
    .withServices(Service.S3);
localstack.start();  // Must start first
URI endpoint = localstack.getEndpoint();  // Works

Not Stopping Container

// WRONG - leaves Docker resources
LocalStackContainer localstack = new LocalStackContainer(dockerImageName)
    .withServices(Service.S3);
localstack.start();
// ... use container
// Container not stopped - resources leaked

// CORRECT
LocalStackContainer localstack = new LocalStackContainer(dockerImageName)
    .withServices(Service.S3);
localstack.start();
try {
    // ... use container
} finally {
    localstack.stop();  // Always stop
}

Using Wrong Endpoint Format

// WRONG - hostname may not work for S3 path-style access
String endpoint = "http://localhost:" + localstack.getMappedPort(4566);
S3Client s3 = S3Client.builder()
    .endpointOverride(URI.create(endpoint))  // May fail
    .build();

// CORRECT - use getEndpoint() which returns IP address
URI endpoint = localstack.getEndpoint();  // Returns IP address
S3Client s3 = S3Client.builder()
    .endpointOverride(endpoint)  // Works correctly
    .forcePathStyle(true)
    .build();

Not Specifying Services for Old Versions

// WRONG - fails for LocalStack < 0.13
LocalStackContainer localstack = new LocalStackContainer(
    DockerImageName.parse("localstack/localstack:0.12")
);
// No services specified - will fail

// CORRECT
LocalStackContainer localstack = new LocalStackContainer(
    DockerImageName.parse("localstack/localstack:0.12")
)
    .withServices(Service.S3);  // Required for < 0.13

Using Deprecated Constructors

// WRONG - deprecated, may break in future
LocalStackContainer localstack = new LocalStackContainer();
LocalStackContainer localstack = new LocalStackContainer("2.0");

// CORRECT
LocalStackContainer localstack = new LocalStackContainer(
    DockerImageName.parse("localstack/localstack:2.0")
);

Not Handling Exceptions

// WRONG - exceptions not handled
localstack.start();
URI endpoint = localstack.getEndpoint();  // May throw IllegalStateException

// CORRECT
try {
    localstack.start();
    URI endpoint = localstack.getEndpoint();
} catch (IllegalStateException e) {
    System.err.println("Failed to start container: " + e.getMessage());
    throw e;
} finally {
    if (localstack.isRunning()) {
        localstack.stop();
    }
}

Performance Considerations

Container Startup Time

  • First container start: 10-30 seconds (image pull, container creation)
  • Subsequent starts: 5-15 seconds (container creation)
  • Service startup: 1-5 seconds per service (lazy loading may add delay)

Resource Usage

  • Memory: ~500MB - 1GB per container
  • Disk: ~1GB for image, additional for data
  • CPU: Low during idle, spikes during service operations

Optimization Tips

  • Use container reuse: localstack.withReuse(true) (requires testcontainers configuration)
  • Use specific image versions (avoid latest for faster pulls)
  • Enable only required services
  • Use JUnit @ClassRule for shared container across tests
  • Consider using LocalStack Pro for better performance

Debugging

Enable Debug Logging

LocalStackContainer localstack = new LocalStackContainer(dockerImageName)
    .withEnv("DEBUG", "1")
    .withServices(Service.S3);

Get Container Logs

localstack.start();
String logs = localstack.getLogs();
System.out.println(logs);

Check Container Status

boolean isRunning = localstack.isRunning();
boolean isCreated = localstack.isCreated();

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