This document describes how to create and configure LocalStack containers, including service selection, environment variables, Docker settings, troubleshooting, and common pitfalls.
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")
);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")
);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 containersECS_DOCKER_FLAGS: Additional Docker flags for ECS containersEAGER_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 featuresDEBUG: 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);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");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
}
}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
);The LocalStackContainer automatically adapts its configuration based on the Docker image version:
// 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/**
* 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";Problem: Container fails to start with timeout error.
Solutions:
localstack.withStartupTimeout(Duration.ofMinutes(5))docker psdocker images | grep localstacklocalstack.getLogs() or docker logs <container-id>LocalStackContainer localstack = new LocalStackContainer(dockerImageName)
.withServices(Service.S3)
.withStartupTimeout(Duration.ofMinutes(5)); // Increase timeoutProblem: Image pull fails.
Solutions:
docker pull localstack/localstack:2.0latestProblem: Container starts but services not available.
Solutions:
localstack.withServices(Service.S3)Problem: Service not found error when calling API.
Solutions:
localstack.withServices(Service.S3)Service.S3.getName() returns "s3"Problem: Multiple services, some not working.
Solutions:
localstack.withServices(Service.S3, Service.SQS)Service.DYNAMODB and Service.DYNAMODB_STREAMS)Problem: Cannot connect to LocalStack from test code.
Solutions:
localstack.start()localstack.getEndpoint() to get correct endpointlocalstack.getMappedPort(4566)Problem: Cannot connect from Docker network.
Solutions:
http://localstack:4566localstack.withNetworkAliases("localstack")localstack.withNetwork(network)Problem: Authentication errors from AWS SDK.
Solutions:
localstack.getAccessKey() and localstack.getSecretKey()start() is calledProblem: Behavior differs from expected (legacy vs modern mode).
Solutions:
getEndpointOverride(Service) for legacy mode service-specific endpoints// 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// 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
}// 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();// 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// 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")
);// 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();
}
}localstack.withReuse(true) (requires testcontainers configuration)latest for faster pulls)@ClassRule for shared container across testsLocalStackContainer localstack = new LocalStackContainer(dockerImageName)
.withEnv("DEBUG", "1")
.withServices(Service.S3);localstack.start();
String logs = localstack.getLogs();
System.out.println(logs);boolean isRunning = localstack.isRunning();
boolean isCreated = localstack.isCreated();Map<String, String> env = localstack.getEnvMap();
System.out.println("HOSTNAME_EXTERNAL: " + env.get("HOSTNAME_EXTERNAL"));
System.out.println("LOCALSTACK_HOST: " + env.get("LOCALSTACK_HOST"));