Testcontainers is a NodeJS library for managing Docker containers during test execution. It provides programmatic control over container lifecycle, enabling developers to create lightweight, throwaway instances of databases, message brokers, web browsers, and any Docker-compatible service for integration testing, end-to-end testing, and local development.
npm install testcontainersimport { GenericContainer, Wait } from 'testcontainers';For CommonJS:
const { GenericContainer, Wait } = require('testcontainers');import { GenericContainer, Wait } from 'testcontainers';
// Start a Redis container
const container = await new GenericContainer('redis:7-alpine')
.withExposedPorts(6379)
.withWaitStrategy(Wait.forLogMessage('Ready to accept connections'))
.start();
// Get connection details
const host = container.getHost();
const port = container.getMappedPort(6379);
// Use the container
// ... your test code here ...
// Clean up
await container.stop();Testcontainers is built around several key components:
GenericContainer class with fluent builder API for configurationCore container lifecycle management with fluent configuration API. Create containers from images or Dockerfiles, configure environment variables, ports, volumes, and resource limits.
class GenericContainer {
constructor(image: string);
static fromDockerfile(context: string, dockerfileName?: string): GenericContainerBuilder;
// Lifecycle
start(): Promise<StartedTestContainer>;
// Configuration
withCommand(command: string[]): this;
withEntrypoint(entrypoint: string[]): this;
withName(name: string): this;
withEnvironment(environment: { [key: string]: string }): this;
withExposedPorts(...ports: PortWithOptionalBinding[]): this;
withBindMounts(bindMounts: BindMount[]): this;
withWaitStrategy(waitStrategy: WaitStrategy): this;
withStartupTimeout(startupTimeoutMs: number): this;
withNetwork(network: StartedNetwork): this;
withNetworkMode(networkMode: string): this;
withNetworkAliases(...networkAliases: string[]): this;
withUser(user: string): this;
withPrivilegedMode(): this;
withHealthCheck(healthCheck: HealthCheck): this;
withWorkingDir(workingDir: string): this;
withReuse(): this;
withPullPolicy(pullPolicy: ImagePullPolicy): this;
}
interface StartedTestContainer {
stop(options?: Partial<StopOptions>): Promise<StoppedTestContainer>;
restart(options?: Partial<RestartOptions>): Promise<void>;
getHost(): string;
getMappedPort(port: number, protocol?: string): number;
getName(): string;
getId(): string;
exec(command: string | string[], opts?: Partial<ExecOptions>): Promise<ExecResult>;
logs(opts?: { since?: number; tail?: number }): Promise<Readable>;
}Manage multi-container environments using Docker Compose files. Configure services, networks, and volumes with per-service wait strategies.
class DockerComposeEnvironment {
constructor(composeFilePath: string, composeFiles: string | string[]);
withBuild(): this;
withEnvironment(environment: { [key: string]: string }): this;
withProfiles(...profiles: string[]): this;
withWaitStrategy(containerName: string, waitStrategy: WaitStrategy): this;
withStartupTimeout(startupTimeoutMs: number): this;
up(services?: Array<string>): Promise<StartedDockerComposeEnvironment>;
}
interface StartedDockerComposeEnvironment {
getContainer(containerName: string): StartedTestContainer;
stop(): Promise<StoppedDockerComposeEnvironment>;
down(options?: Partial<ComposeDownOptions>): Promise<DownedDockerComposeEnvironment>;
}Create and manage Docker networks for container communication and isolation.
class Network {
start(): Promise<StartedNetwork>;
}
interface StartedNetwork {
getId(): string;
getName(): string;
stop(): Promise<StoppedNetwork>;
}Flexible strategies for determining when containers are ready for use. Supports health checks, log messages, HTTP endpoints, port checks, and shell commands.
class Wait {
static forAll(waitStrategies: WaitStrategy[]): WaitStrategy;
static forListeningPorts(): WaitStrategy;
static forLogMessage(message: string | RegExp, times?: number): WaitStrategy;
static forHealthCheck(): WaitStrategy;
static forHttp(path: string, port: number, options?: HttpWaitStrategyOptions): HttpWaitStrategy;
static forSuccessfulCommand(command: string): WaitStrategy;
}
interface WaitStrategy {
withStartupTimeout(startupTimeoutMs: number): WaitStrategy;
}
interface HttpWaitStrategy extends WaitStrategy {
forStatusCode(statusCode: number): this;
forStatusCodeMatching(predicate: (statusCode: number) => boolean): this;
withMethod(method: string): this;
withHeaders(headers: { [key: string]: string }): this;
withBasicCredentials(username: string, password: string): this;
usingTls(): this;
}Helper classes and functions for advanced use cases including port management, image naming, logging, retry logic, and host port exposure.
class TestContainers {
static exposeHostPorts(...ports: number[]): Promise<void>;
}
function getContainerRuntimeClient(): Promise<ContainerRuntimeClient>;
class ImageName {
constructor(registry: string | undefined, image: string, tag: string);
static fromString(string: string): ImageName;
readonly registry: string | undefined;
readonly image: string;
readonly tag: string;
readonly string: string;
}type Environment = { [key: string]: string };
type BindMode = 'rw' | 'ro' | 'z' | 'Z';
interface BindMount {
source: string;
target: string;
mode?: BindMode;
}
interface HealthCheck {
test: ['CMD-SHELL', string] | ['CMD', ...string[]];
interval?: number;
timeout?: number;
retries?: number;
startPeriod?: number;
}
interface ExecOptions {
workingDir?: string;
user?: string;
env?: { [key: string]: string };
}
interface ExecResult {
output: string;
stdout: string;
stderr: string;
exitCode: number;
}
interface StopOptions {
timeout: number;
remove: boolean;
removeVolumes: boolean;
}
interface RestartOptions {
timeout: number;
}
interface HttpWaitStrategyOptions {
abortOnContainerExit?: boolean;
}
interface ComposeDownOptions {
timeout?: number;
removeVolumes?: boolean;
}
type PortWithOptionalBinding =
| number
| `${number}/${'tcp' | 'udp'}`
| PortWithBinding;
interface PortWithBinding {
container: number;
host: number;
protocol?: 'tcp' | 'udp';
}
type ContainerRuntime = 'docker' | 'podman';
type HealthCheckStatus = 'none' | 'starting' | 'unhealthy' | 'healthy';
type HostPortBindings = Array<{ hostIp: string; hostPort: number }>;
type Ports = { [containerPortWithProtocol: string]: HostPortBindings };
interface NetworkSettings {
networkId: string;
ipAddress: string;
}
interface InspectResult {
name: string;
hostname: string;
ports: Ports;
healthCheckStatus: HealthCheckStatus;
networkSettings: { [networkName: string]: NetworkSettings };
state: {
status: string;
running: boolean;
startedAt: Date;
finishedAt: Date | undefined;
};
labels: { [key: string]: string };
}