LocalStack module for Testcontainers that enables developers to programmatically start and manage LocalStack containers for testing AWS services locally. It provides a type-safe API for creating LocalStack containers with automatic port exposure, configurable wait strategies, and automatic hostname resolution for different networking scenarios.
Required Dependencies:
@testcontainers/localstack (this package)testcontainers package is required (provided transitively as peer dependency)@aws-sdk/client-s3, @aws-sdk/client-sqs, @aws-sdk/client-lambda)Default Behaviors:
4566 (LocalStack service port, automatically exposed and mapped to random host port)localstack/localstack:3.0 or similar)localhost (unless network aliases or LOCALSTACK_HOST configured)getPort() or getConnectionUri() to retrieve)accessKeyId: 'test', secretAccessKey: 'test') for LocalStackThreading Model:
start() method is async and must be awaitedstop() method is async and must be awaitedLifecycle:
await container.start() before usestart() resolvesawait container.stop() for cleanupstop() even on errorsExceptions:
ContainerStartException - Container failed to start (timeout, image pull failure, etc.)PortBindingException - Port binding conflictsDockerNotAvailableException - Docker daemon not accessibleImagePullException - Failed to pull Docker imageTimeoutError - Health check timeout (container started but not ready)S3ServiceException, SQSServiceException)Edge Cases:
withStartupTimeout())withReuse(true) to reuse containers across test runs (requires testcontainers configuration)withNetwork() and withNetworkAliases() for multi-container testsforcePathStyle: true for S3 clients when connecting to LocalStackus-east-1 is commonly used for testingtest/test is standard for testingnpm install @testcontainers/localstack --save-devNote on Dependencies: The @testcontainers/localstack package includes testcontainers as a peer dependency. If you're also using the testcontainers package directly in your project for advanced features like custom networks, ensure you're using compatible versions to avoid TypeScript type conflicts.
import { LocalstackContainer, StartedLocalStackContainer } from '@testcontainers/localstack';For CommonJS:
const { LocalstackContainer, StartedLocalStackContainer } = require('@testcontainers/localstack');import { LocalstackContainer } from '@testcontainers/localstack';
import { S3Client, CreateBucketCommand, HeadBucketCommand } from '@aws-sdk/client-s3';
// Start a LocalStack container
const container = await new LocalstackContainer('localstack/localstack:3.0').start();
// Create an AWS SDK client pointing to LocalStack
const client = new S3Client({
endpoint: container.getConnectionUri(),
forcePathStyle: true,
region: 'us-east-1',
credentials: {
secretAccessKey: 'test',
accessKeyId: 'test',
},
});
// Use AWS services
const createBucketCommand = new CreateBucketCommand({ Bucket: 'testcontainers' });
await client.send(createBucketCommand);
const headBucketCommand = new HeadBucketCommand({ Bucket: 'testcontainers' });
const response = await client.send(headBucketCommand);
console.log(response.$metadata.httpStatusCode); // 200
// Stop the container when done
await container.stop();import { LocalstackContainer } from '@testcontainers/localstack';
import { S3Client, CreateBucketCommand } from '@aws-sdk/client-s3';
let container: StartedLocalStackContainer | null = null;
let client: S3Client | null = null;
try {
container = await new LocalstackContainer('localstack/localstack:3.0').start();
client = new S3Client({
endpoint: container.getConnectionUri(),
forcePathStyle: true,
region: 'us-east-1',
credentials: {
secretAccessKey: 'test',
accessKeyId: 'test',
},
});
const createBucketCommand = new CreateBucketCommand({ Bucket: 'testcontainers' });
await client.send(createBucketCommand);
} catch (error) {
console.error('Test failed:', error);
throw error;
} finally {
if (client) {
client.destroy();
}
if (container) {
await container.stop();
}
}The LocalStack module is built on the Testcontainers framework and provides:
GenericContainer from the testcontainers packageCreate and configure a LocalStack container instance.
class LocalstackContainer extends GenericContainer {
/**
* Creates a new LocalStack container with the specified Docker image
* @param image - Docker image name (e.g., 'localstack/localstack:3.0')
* @throws {DockerException} - If Docker daemon is not available
*/
constructor(image: string);
/**
* Starts the container and returns a StartedLocalStackContainer instance
* @returns Promise resolving to a started container
* @throws {ContainerStartException} - If container fails to start
* @throws {TimeoutError} - If health check times out
* @throws {ImagePullException} - If image pull fails
*/
start(): Promise<StartedLocalStackContainer>;
}Usage Example:
import { LocalstackContainer } from '@testcontainers/localstack';
// Create and start a container
const container = await new LocalstackContainer('localstack/localstack:3.0').start();The LocalstackContainer class extends GenericContainer from the testcontainers package, which provides additional configuration methods:
Configuration Methods (inherited from GenericContainer):
/**
* Set environment variables on the container
* @param environment - Object with key-value pairs or single key-value
*/
withEnvironment(environment: { [key: string]: string }): this;
withEnvironment(key: string, value: string): this;
/**
* Configure the container to use a specific Docker network
* @param network - Network instance from testcontainers
*/
withNetwork(network: Network): this;
/**
* Set network aliases for the container
* @param aliases - One or more network alias strings
*/
withNetworkAliases(...aliases: string[]): this;
/**
* Add additional exposed ports
* @param ports - Port numbers to expose
*/
withExposedPorts(...ports: number[]): this;
/**
* Set a custom wait strategy
* @param waitStrategy - WaitStrategy instance
*/
withWaitStrategy(waitStrategy: WaitStrategy): this;
/**
* Set the startup timeout in milliseconds
* @param timeout - Timeout duration
*/
withStartupTimeout(timeout: Duration): this;
/**
* Set the container command
* @param command - Command array
*/
withCommand(command: string[]): this;
/**
* Copy files or directories to the container before it starts
* @param filesToCopy - Array of file copy configurations
*/
withCopyFilesToContainer(filesToCopy: CopyFilesToContainer[]): this;
/**
* Bind mount a volume
* @param bindMounts - Array of bind mount configurations
*/
withBindMounts(bindMounts: BindMount[]): this;
/**
* Set temporary filesystem mounts
* @param tmpFs - Object mapping paths to mount options
*/
withTmpFs(tmpFs: { [key: string]: string }): this;
/**
* Set the user to run the container as
* @param user - User string (e.g., 'root', '1000:1000')
*/
withUser(user: string): this;
/**
* Enable privileged mode
*/
withPrivilegedMode(): this;
/**
* Enable container reuse across test runs
* @param reuse - Boolean to enable/disable reuse
*/
withReuse(reuse: boolean): this;Advanced Configuration Example:
import { LocalstackContainer } from '@testcontainers/localstack';
import { Network } from 'testcontainers';
// Create a custom network
const network = await new Network().start();
// Create container with custom configuration
const container = await new LocalstackContainer('localstack/localstack:3.0')
.withNetwork(network)
.withNetworkAliases('localstack')
.withEnvironment({
SERVICES: 's3,sqs,lambda',
DEBUG: '1'
})
.start();Access connection information and manage running LocalStack containers.
class StartedLocalStackContainer extends AbstractStartedContainer {
/**
* Returns the mapped host port for the LocalStack service (4566)
* @returns The host port number that maps to LocalStack's port 4566
* @throws {Error} - If container is not running
*/
getPort(): number;
/**
* Returns a connection URI for connecting to LocalStack
* @returns A connection URI in the form of `http://host:port`
* @throws {Error} - If container is not running
*/
getConnectionUri(): string;
}The StartedLocalStackContainer class extends AbstractStartedContainer from the testcontainers package, which provides additional container management methods:
Container Management Methods (inherited from AbstractStartedContainer):
/**
* Get the container's host address
* @returns Host address string
*/
getHost(): string;
/**
* Get the container's hostname
* @returns Hostname string
*/
getHostname(): string;
/**
* Get the container ID
* @returns Container ID string
*/
getId(): string;
/**
* Get the container name
* @returns Container name string
*/
getName(): string;
/**
* Get the first mapped port
* @returns Port number
*/
getFirstMappedPort(): number;
/**
* Get the mapped port for a container port
* @param port - Container port number
* @param protocol - Protocol ('tcp' or 'udp')
* @returns Mapped host port number
*/
getMappedPort(port: number, protocol?: string): number;
getMappedPort(portWithProtocol: `${number}/${"tcp" | "udp"}`): number;
/**
* Get container labels
* @returns Labels object
*/
getLabels(): Labels;
/**
* Get the container's network names
* @returns Array of network names
*/
getNetworkNames(): string[];
/**
* Get the network ID for a specific network
* @param networkName - Network name
* @returns Network ID string
*/
getNetworkId(networkName: string): string;
/**
* Get the container's IP address on a specific network
* @param networkName - Network name
* @returns IP address string
*/
getIpAddress(networkName: string): string;
/**
* Stop the container
* @param options - Optional stop configuration
* @returns Promise resolving to stopped container
*/
stop(options?: Partial<StopOptions>): Promise<StoppedTestContainer>;
/**
* Restart the container
* @param options - Optional restart configuration
* @returns Promise that resolves when container is restarted
*/
restart(options?: Partial<RestartOptions>): Promise<void>;
/**
* Commit the container to create a new image
* @param options - Commit options
* @returns Promise resolving to image ID
*/
commit(options: CommitOptions): Promise<string>;
/**
* Get the container logs
* @param opts - Log options (since, tail)
* @returns Promise resolving to readable stream
*/
logs(opts?: { since?: number; tail?: number }): Promise<Readable>;
/**
* Execute a command in the running container
* @param command - Command string or array
* @param opts - Execution options
* @returns Promise resolving to execution result
*/
exec(command: string | string[], opts?: Partial<ExecOptions>): Promise<ExecResult>;
/**
* Copy files to the container
* @param filesToCopy - Array of file copy configurations
*/
copyFilesToContainer(filesToCopy: FileToCopy[]): Promise<void>;
/**
* Copy directories to the container
* @param directoriesToCopy - Array of directory copy configurations
*/
copyDirectoriesToContainer(directoriesToCopy: DirectoryToCopy[]): Promise<void>;
/**
* Copy content to the container
* @param contentsToCopy - Array of content copy configurations
*/
copyContentToContainer(contentsToCopy: ContentToCopy[]): Promise<void>;
/**
* Copy a tar archive to the container
* @param tar - Readable stream containing tar archive
* @param target - Target path in container
*/
copyArchiveToContainer(tar: Readable, target?: string): Promise<void>;
/**
* Copy a tar archive from the container
* @param path - Source path in container
* @returns Promise resolving to readable stream
*/
copyArchiveFromContainer(path: string): Promise<NodeJS.ReadableStream>;Usage Example:
import { LocalstackContainer } from '@testcontainers/localstack';
const container = await new LocalstackContainer('localstack/localstack:3.0').start();
// Get connection details
const host = container.getHost();
const port = container.getPort();
const uri = container.getConnectionUri();
console.log(`LocalStack is running at ${uri}`);
// Execute a command in the container
const result = await container.exec(['printenv', 'LOCALSTACK_HOST']);
console.log(result.output);
// Get container logs
const logs = await container.logs();
logs.on('data', (line) => console.log(line.toString()));
// Stop the container
await container.stop();The LocalStack module automatically configures the LOCALSTACK_HOST environment variable based on your networking setup:
LOCALSTACK_HOST explicitly via withEnvironment(), that value is usedwithNetworkAliases(), the last alias is usedlocalhostNetwork Example:
import { LocalstackContainer } from '@testcontainers/localstack';
import { Network, GenericContainer } from 'testcontainers';
// Create a network
const network = await new Network().start();
try {
// Start LocalStack with network alias
const localstack = await new LocalstackContainer('localstack/localstack:3.0')
.withNetwork(network)
.withNetworkAliases('localstack')
.start();
// Start another container on the same network
const appContainer = await new GenericContainer('my-app:latest')
.withNetwork(network)
.withEnvironment({
AWS_ENDPOINT: 'http://localstack:4566'
})
.start();
// The app container can now reach LocalStack via the 'localstack' hostname
} finally {
await localstack?.stop();
await appContainer?.stop();
await network.stop();
}The LocalStack module automatically configures LAMBDA_DOCKER_FLAGS to include the Testcontainers session ID label. This ensures that Lambda containers started by LocalStack are properly tracked and cleaned up by the Testcontainers Reaper when your tests finish.
Lambda Example:
import { LocalstackContainer } from '@testcontainers/localstack';
import { LambdaClient, CreateFunctionCommand, InvokeCommand } from '@aws-sdk/client-lambda';
const container = await new LocalstackContainer('localstack/localstack:3.0')
.withEnvironment({
SERVICES: 'lambda'
})
.start();
const lambdaClient = new LambdaClient({
endpoint: container.getConnectionUri(),
region: 'us-east-1',
credentials: {
secretAccessKey: 'test',
accessKeyId: 'test',
},
});
// Create and invoke Lambda functions
// Lambda containers will be automatically cleaned up
const createFunctionCommand = new CreateFunctionCommand({
FunctionName: 'test-function',
Runtime: 'nodejs18.x',
Handler: 'index.handler',
Role: 'arn:aws:iam::123456789012:role/lambda-role',
Code: {
ZipFile: Buffer.from('exports.handler = async () => ({ statusCode: 200, body: "Hello" });')
}
});
await lambdaClient.send(createFunctionCommand);
await container.stop();You can override or add environment variables to customize LocalStack's behavior:
import { LocalstackContainer } from '@testcontainers/localstack';
const container = await new LocalstackContainer('localstack/localstack:3.0')
.withEnvironment({
SERVICES: 's3,sqs,dynamodb', // Only start specific services
DEBUG: '1', // Enable debug mode
LOCALSTACK_HOST: 'myhost', // Override hostname resolution
SQS_ENDPOINT_STRATEGY: 'path', // Configure SQS endpoint strategy
LAMBDA_DOCKER_FLAGS: '-l mylabel=myvalue', // Add custom Docker flags for Lambda
PERSISTENCE: '1', // Enable persistence (requires volume mount)
DATA_DIR: '/tmp/localstack/data', // Set data directory for persistence
})
.start();Common Environment Variables:
SERVICES: Comma-separated list of AWS services to start (e.g., 's3,sqs,lambda')DEBUG: Set to '1' to enable debug loggingLOCALSTACK_HOST: Override hostname resolutionLAMBDA_DOCKER_FLAGS: Custom Docker flags for Lambda containers (session ID is automatically appended)PERSISTENCE: Set to '1' to enable data persistence (requires volume mount)DATA_DIR: Directory for persistent data storageSQS_ENDPOINT_STRATEGY: SQS endpoint strategy ('path' or 'domain')LAMBDA_EXECUTOR: Lambda execution mode ('local' or 'docker')Note: When you provide LAMBDA_DOCKER_FLAGS, the Testcontainers session ID label will be automatically appended to your custom flags.
import { LocalstackContainer } from '@testcontainers/localstack';
import { S3Client, CreateBucketCommand, PutObjectCommand, GetObjectCommand, DeleteBucketCommand } from '@aws-sdk/client-s3';
const container = await new LocalstackContainer('localstack/localstack:3.0')
.withEnvironment({ SERVICES: 's3' })
.start();
const s3Client = new S3Client({
endpoint: container.getConnectionUri(),
forcePathStyle: true, // Required for LocalStack
region: 'us-east-1',
credentials: {
secretAccessKey: 'test',
accessKeyId: 'test',
},
});
// Create bucket
await s3Client.send(new CreateBucketCommand({ Bucket: 'test-bucket' }));
// Put object
await s3Client.send(new PutObjectCommand({
Bucket: 'test-bucket',
Key: 'test-key',
Body: 'test content'
}));
// Get object
const getResponse = await s3Client.send(new GetObjectCommand({
Bucket: 'test-bucket',
Key: 'test-key'
}));
// Cleanup
await s3Client.send(new DeleteBucketCommand({ Bucket: 'test-bucket' }));
await container.stop();import { LocalstackContainer } from '@testcontainers/localstack';
import { SQSClient, CreateQueueCommand, SendMessageCommand, ReceiveMessageCommand, DeleteQueueCommand } from '@aws-sdk/client-sqs';
const container = await new LocalstackContainer('localstack/localstack:3.0')
.withEnvironment({ SERVICES: 'sqs' })
.start();
const sqsClient = new SQSClient({
endpoint: container.getConnectionUri(),
region: 'us-east-1',
credentials: {
secretAccessKey: 'test',
accessKeyId: 'test',
},
});
// Create queue
const createResponse = await sqsClient.send(new CreateQueueCommand({
QueueName: 'test-queue'
}));
const queueUrl = createResponse.QueueUrl!;
// Send message
await sqsClient.send(new SendMessageCommand({
QueueUrl: queueUrl,
MessageBody: 'test message'
}));
// Receive message
const receiveResponse = await sqsClient.send(new ReceiveMessageCommand({
QueueUrl: queueUrl
}));
// Cleanup
await sqsClient.send(new DeleteQueueCommand({ QueueUrl: queueUrl }));
await container.stop();import { LocalstackContainer } from '@testcontainers/localstack';
import { DynamoDBClient, CreateTableCommand, PutItemCommand, GetItemCommand, DeleteTableCommand } from '@aws-sdk/client-dynamodb';
const container = await new LocalstackContainer('localstack/localstack:3.0')
.withEnvironment({ SERVICES: 'dynamodb' })
.start();
const dynamoClient = new DynamoDBClient({
endpoint: container.getConnectionUri(),
region: 'us-east-1',
credentials: {
secretAccessKey: 'test',
accessKeyId: 'test',
},
});
// Create table
await dynamoClient.send(new CreateTableCommand({
TableName: 'test-table',
KeySchema: [
{ AttributeName: 'id', KeyType: 'HASH' }
],
AttributeDefinitions: [
{ AttributeName: 'id', AttributeType: 'S' }
],
BillingMode: 'PAY_PER_REQUEST'
}));
// Put item
await dynamoClient.send(new PutItemCommand({
TableName: 'test-table',
Item: {
id: { S: '1' },
name: { S: 'test' }
}
}));
// Get item
const getResponse = await dynamoClient.send(new GetItemCommand({
TableName: 'test-table',
Key: { id: { S: '1' } }
}));
// Cleanup
await dynamoClient.send(new DeleteTableCommand({ TableName: 'test-table' }));
await container.stop();import { LocalstackContainer } from '@testcontainers/localstack';
import { S3Client, CreateBucketCommand } from '@aws-sdk/client-s3';
describe('AWS Service Tests', () => {
let container: StartedLocalStackContainer;
let s3Client: S3Client;
beforeAll(async () => {
container = await new LocalstackContainer('localstack/localstack:3.0').start();
s3Client = new S3Client({
endpoint: container.getConnectionUri(),
forcePathStyle: true,
region: 'us-east-1',
credentials: {
secretAccessKey: 'test',
accessKeyId: 'test',
},
});
});
afterAll(async () => {
s3Client.destroy();
await container.stop();
});
it('should create an S3 bucket', async () => {
await s3Client.send(new CreateBucketCommand({ Bucket: 'test-bucket' }));
});
});import { LocalstackContainer } from '@testcontainers/localstack';
import { S3Client, CreateBucketCommand } from '@aws-sdk/client-s3';
describe('AWS Service Tests', function () {
let container: StartedLocalStackContainer;
let s3Client: S3Client;
before(async function () {
container = await new LocalstackContainer('localstack/localstack:3.0').start();
s3Client = new S3Client({
endpoint: container.getConnectionUri(),
forcePathStyle: true,
region: 'us-east-1',
credentials: {
secretAccessKey: 'test',
accessKeyId: 'test',
},
});
});
after(async function () {
s3Client.destroy();
await container.stop();
});
it('should create an S3 bucket', async function () {
await s3Client.send(new CreateBucketCommand({ Bucket: 'test-bucket' }));
});
});import { LocalstackContainer } from '@testcontainers/localstack';
import { S3Client, CreateBucketCommand } from '@aws-sdk/client-s3';
describe('AWS Service Tests', () => {
it('should create an S3 bucket', async () => {
const container = await new LocalstackContainer('localstack/localstack:3.0').start();
try {
const s3Client = new S3Client({
endpoint: container.getConnectionUri(),
forcePathStyle: true,
region: 'us-east-1',
credentials: {
secretAccessKey: 'test',
accessKeyId: 'test',
},
});
await s3Client.send(new CreateBucketCommand({ Bucket: 'test-bucket' }));
s3Client.destroy();
} finally {
await container.stop();
}
});
});import { LocalstackContainer } from '@testcontainers/localstack';
import { S3Client, CreateBucketCommand } from '@aws-sdk/client-s3';
// Each test gets its own container
const test1 = async () => {
const container = await new LocalstackContainer('localstack/localstack:3.0').start();
try {
const s3Client = new S3Client({
endpoint: container.getConnectionUri(),
forcePathStyle: true,
region: 'us-east-1',
credentials: { secretAccessKey: 'test', accessKeyId: 'test' },
});
await s3Client.send(new CreateBucketCommand({ Bucket: 'bucket1' }));
s3Client.destroy();
} finally {
await container.stop();
}
};
const test2 = async () => {
const container = await new LocalstackContainer('localstack/localstack:3.0').start();
try {
const s3Client = new S3Client({
endpoint: container.getConnectionUri(),
forcePathStyle: true,
region: 'us-east-1',
credentials: { secretAccessKey: 'test', accessKeyId: 'test' },
});
await s3Client.send(new CreateBucketCommand({ Bucket: 'bucket2' }));
s3Client.destroy();
} finally {
await container.stop();
}
};
// Run in parallel - each gets unique ports
await Promise.all([test1(), test2()]);import { LocalstackContainer } from '@testcontainers/localstack';
import { Network } from 'testcontainers';
import { S3Client, CreateBucketCommand } from '@aws-sdk/client-s3';
// Create shared network
const network = await new Network().start();
try {
// Create multiple containers on same network
const container1 = await new LocalstackContainer('localstack/localstack:3.0')
.withNetwork(network)
.withNetworkAliases('localstack1')
.start();
const container2 = await new LocalstackContainer('localstack/localstack:3.0')
.withNetwork(network)
.withNetworkAliases('localstack2')
.start();
// Each container has its own endpoint
const s3Client1 = new S3Client({
endpoint: container1.getConnectionUri(),
forcePathStyle: true,
region: 'us-east-1',
credentials: { secretAccessKey: 'test', accessKeyId: 'test' },
});
const s3Client2 = new S3Client({
endpoint: container2.getConnectionUri(),
forcePathStyle: true,
region: 'us-east-1',
credentials: { secretAccessKey: 'test', accessKeyId: 'test' },
});
// Use both containers...
} finally {
await container1?.stop();
await container2?.stop();
await network.stop();
}The package exports the following constants:
/**
* The default LocalStack service port
*/
const LOCALSTACK_PORT: 4566;The main types are exported from the package. Additional types are inherited from the testcontainers package:
import type {
Network,
WaitStrategy,
BindMount,
CopyFilesToContainer,
FileToCopy,
DirectoryToCopy,
ContentToCopy,
ExecResult,
ExecOptions,
StoppedTestContainer,
StopOptions,
RestartOptions,
CommitOptions,
Labels,
Duration
} from 'testcontainers';
import type { Readable } from 'stream';Container operations can throw errors. It's recommended to handle them appropriately:
import { LocalstackContainer } from '@testcontainers/localstack';
import { S3Client, CreateBucketCommand, S3ServiceException } from '@aws-sdk/client-s3';
let container: StartedLocalStackContainer | null = null;
let s3Client: S3Client | null = null;
try {
container = await new LocalstackContainer('localstack/localstack:3.0').start();
s3Client = new S3Client({
endpoint: container.getConnectionUri(),
forcePathStyle: true,
region: 'us-east-1',
credentials: {
secretAccessKey: 'test',
accessKeyId: 'test',
},
});
await s3Client.send(new CreateBucketCommand({ Bucket: 'test-bucket' }));
} catch (error) {
if (error instanceof ContainerStartException) {
console.error('Container failed to start:', error.message);
// Check Docker daemon, image availability, port conflicts
} else if (error instanceof TimeoutError) {
console.error('Container health check timed out');
// Increase startup timeout or check container logs
} else if (error instanceof S3ServiceException) {
console.error('S3 service error:', error.message);
// Handle AWS service-specific errors
} else {
console.error('Unexpected error:', error);
}
throw error;
} finally {
if (s3Client) {
s3Client.destroy();
}
if (container) {
await container.stop();
}
}Common Error Scenarios:
withStartupTimeout() or check system resourcesSERVICES environment variabletest/test for LocalStack)import { LocalstackContainer } from '@testcontainers/localstack';
import { Wait, Duration } from 'testcontainers';
const container = await new LocalstackContainer('localstack/localstack:3.0')
.withWaitStrategy(
Wait.forHttp('/_localstack/health', 4566)
.forStatusCode(200)
.withStartupTimeout(Duration.ofSeconds(300))
)
.start();import { LocalstackContainer } from '@testcontainers/localstack';
// Enable container reuse (requires testcontainers configuration)
const container = await new LocalstackContainer('localstack/localstack:3.0')
.withReuse(true)
.start();
// Container will not be removed on stop() if reuse is enabledimport { LocalstackContainer } from '@testcontainers/localstack';
// Enable persistence with volume mount
const container = await new LocalstackContainer('localstack/localstack:3.0')
.withEnvironment({
PERSISTENCE: '1',
DATA_DIR: '/tmp/localstack/data'
})
.withBindMounts([
{
source: './localstack-data',
target: '/tmp/localstack/data'
}
])
.start();import { LocalstackContainer } from '@testcontainers/localstack';
import { Duration } from 'testcontainers';
// Increase startup timeout for slower systems
const container = await new LocalstackContainer('localstack/localstack:3.0')
.withStartupTimeout(Duration.ofSeconds(300))
.start();import { LocalstackContainer } from '@testcontainers/localstack';
import { OutputFrame } from 'testcontainers';
const container = await new LocalstackContainer('localstack/localstack:3.0')
.withLogConsumer((frame: OutputFrame) => {
console.log(frame.getUtf8String());
})
.start();Container Won't Start:
docker pslocalstack/localstack:3.0)await container.logs()Connection Refused:
await container.start() completed successfullystart() resolves for container to be fully readycontainer.getConnectionUri() and container.getPort()SERVICES environment variableHealth Check Timeout:
.withStartupTimeout(Duration.ofSeconds(300))Port Conflicts in CI/CD:
Resource Exhaustion:
docker ps -adocker container prunedocker statsImage Pull Failures:
docker pull localstack/localstack:3.0AWS SDK Connection Errors:
forcePathStyle: true is set for S3 clientshttp://host:porttest/test for LocalStack)us-east-1 is common)Service Not Available:
SERVICES environment variableLambda Container Cleanup Issues:
LAMBDA_DOCKER_FLAGS includes session tracking (automatic)docker ps -a | grep lambdadocker container prune