Helper classes and functions for advanced use cases including host port exposure, container runtime access, image name parsing, port management, logging, and retry logic.
Static utility class for global testcontainers operations.
/**
* Utility class for testcontainers operations
*/
class TestContainers {
/**
* Expose host ports to containers via SSH tunnel
* Allows containers to access services running on the host machine
* @param ports - Port numbers to expose from host to containers
*/
static exposeHostPorts(...ports: number[]): Promise<void>;
}Usage Example:
import { TestContainers, GenericContainer } from 'testcontainers';
// Expose host services to containers
// Useful when containers need to access services on host (e.g., local dev server)
await TestContainers.exposeHostPorts(3000, 5432);
// Now containers can access host:3000 and host:5432
const container = await new GenericContainer('test-client:latest')
.withEnvironment({
API_URL: 'http://host.testcontainers.internal:3000',
DB_URL: 'postgresql://host.testcontainers.internal:5432/db'
})
.start();Access the underlying container runtime (Docker or Podman) for advanced operations.
/**
* Get the container runtime client
* @returns Promise resolving to container runtime client
*/
function getContainerRuntimeClient(): Promise<ContainerRuntimeClient>;
/**
* Container runtime client providing access to container, image, and network operations
*/
interface ContainerRuntimeClient {
/** Runtime information (Docker/Podman version, host, etc.) */
readonly info: Info;
/** Docker Compose operations client */
readonly compose: ComposeClient;
/** Container operations client */
readonly container: ContainerClient;
/** Image operations client */
readonly image: ImageClient;
/** Network operations client */
readonly network: NetworkClient;
}
interface Info {
node: NodeInfo;
containerRuntime: ContainerRuntimeInfo;
}
interface NodeInfo {
version: string;
architecture: string;
platform: string;
}
interface ContainerRuntimeInfo {
host: string;
hostIps: HostIp[];
remoteSocketPath?: string;
indexServerAddress: string;
serverVersion: string;
operatingSystem: string;
operatingSystemType: string;
architecture: string;
cpus: number;
memory: number;
runtimes: string[];
labels: { [key: string]: string };
}
interface HostIp {
address: string;
family: number;
}Usage Example:
import { getContainerRuntimeClient } from 'testcontainers';
// Get runtime client
const client = await getContainerRuntimeClient();
// Inspect runtime information
const { info } = client;
console.log('Container Runtime:', info.containerRuntime.serverVersion);
console.log('Operating System:', info.containerRuntime.operatingSystem);
console.log('Architecture:', info.containerRuntime.architecture);
console.log('Available CPUs:', info.containerRuntime.cpus);
console.log('Total Memory:', info.containerRuntime.memory);
console.log('Host IPs:', info.containerRuntime.hostIps);
// Access low-level clients for advanced operations
const { container, image, network } = client;
// Use these clients for operations not exposed by high-level APIParse and manipulate Docker image names.
/**
* Represents a parsed Docker image name
*/
class ImageName {
/**
* Create an image name from components
* @param registry - Registry hostname (undefined for Docker Hub)
* @param image - Image name (e.g., 'library/redis', 'myorg/myapp')
* @param tag - Image tag (e.g., 'latest', '1.0.0', 'sha256:abc123')
*/
constructor(registry: string | undefined, image: string, tag: string);
/**
* Parse image name from string
* @param string - Full image name (e.g., 'redis:7', 'gcr.io/myproject/myapp:latest')
* @returns Parsed ImageName instance
*/
static fromString(string: string): ImageName;
/**
* Compare two image names for equality
* @param other - Image name to compare with
* @returns True if image names are identical
*/
equals(other: ImageName): boolean;
/** Registry hostname (undefined for Docker Hub) */
readonly registry: string | undefined;
/** Image name */
readonly image: string;
/** Image tag */
readonly tag: string;
/** Full image name string */
readonly string: string;
}Usage Examples:
import { ImageName } from 'testcontainers';
// Parse image names
const redis = ImageName.fromString('redis:7-alpine');
console.log(redis.registry); // undefined (Docker Hub)
console.log(redis.image); // 'redis'
console.log(redis.tag); // '7-alpine'
console.log(redis.string); // 'redis:7-alpine'
const gcr = ImageName.fromString('gcr.io/my-project/my-app:v1.2.3');
console.log(gcr.registry); // 'gcr.io'
console.log(gcr.image); // 'my-project/my-app'
console.log(gcr.tag); // 'v1.2.3'
console.log(gcr.string); // 'gcr.io/my-project/my-app:v1.2.3'
// Create image names programmatically
const custom = new ImageName('myregistry.com', 'myorg/myapp', 'latest');
console.log(custom.string); // 'myregistry.com/myorg/myapp:latest'
// Compare image names
const img1 = ImageName.fromString('postgres:14');
const img2 = ImageName.fromString('postgres:14');
const img3 = ImageName.fromString('postgres:15');
console.log(img1.equals(img2)); // true
console.log(img1.equals(img3)); // falseManage port bindings between container and host ports.
/**
* Manages port bindings between container and host
*/
class BoundPorts {
/**
* Get host port bound to container port
* @param port - Container port number or string
* @param protocol - Protocol ('tcp' or 'udp', default: 'tcp')
* @returns Host port number
*/
getBinding(port: number | string, protocol?: string): number;
/**
* Get the first bound port
* @returns First host port number
*/
getFirstBinding(): number;
/**
* Set a port binding
* @param key - Container port
* @param value - Host port
* @param protocol - Protocol (default: 'tcp')
*/
setBinding(key: string | number, value: number, protocol?: string): void;
/**
* Iterate over all bindings
* @returns Iterable of [portKey, hostPort] pairs
*/
iterator(): Iterable<[string, number]>;
/**
* Filter bindings to only include specified ports
* @param ports - Ports to include
* @returns New BoundPorts with filtered bindings
*/
filter(ports: PortWithOptionalBinding[]): BoundPorts;
/**
* Create BoundPorts from container inspection result
* @param hostIps - Available host IPs
* @param inspectResult - Container inspection result
* @returns BoundPorts instance
*/
static fromInspectResult(hostIps: HostIp[], inspectResult: InspectResult): BoundPorts;
}Utility functions for working with port specifications.
/**
* Extract container port from port specification
* @param port - Port specification
* @returns Container port number
*/
function getContainerPort(port: PortWithOptionalBinding): number;
/**
* Check if port has explicit host binding
* @param port - Port specification
* @returns True if port has host binding
*/
function hasHostBinding(port: PortWithOptionalBinding): port is PortWithBinding;
type PortWithOptionalBinding =
| number
| `${number}/${'tcp' | 'udp'}`
| PortWithBinding;
interface PortWithBinding {
container: number;
host: number;
protocol?: 'tcp' | 'udp';
}Usage Examples:
import { getContainerPort, hasHostBinding } from 'testcontainers';
// Extract container ports
const port1 = getContainerPort(8080); // 8080
const port2 = getContainerPort('9000/tcp'); // 9000
const port3 = getContainerPort({ container: 3000, host: 3001 }); // 3000
// Check for host bindings
const simplePort = 8080;
const boundPort = { container: 3000, host: 3001 };
console.log(hasHostBinding(simplePort)); // false
console.log(hasHostBinding(boundPort)); // true
if (hasHostBinding(boundPort)) {
console.log('Host port:', boundPort.host);
}Interface for generating available ports.
/**
* Interface for port generation strategies
*/
interface PortGenerator {
/**
* Generate an available port
* @returns Promise resolving to port number
*/
generatePort(): Promise<number>;
}
/**
* Generates random available ports
*/
class RandomPortGenerator implements PortGenerator {
/**
* Generate a random available port
* @returns Promise resolving to available port number
*/
generatePort(): Promise<number>;
}Factory for image pull policies.
/**
* Factory for image pull policies
*/
class PullPolicy {
/**
* Get default pull policy (pull if not present)
* @returns Default pull policy
*/
static defaultPolicy(): ImagePullPolicy;
/**
* Get always pull policy (pull on every start)
* @returns Always pull policy
*/
static alwaysPull(): ImagePullPolicy;
}
interface ImagePullPolicy {
shouldPull(): boolean;
}Usage Example:
import { GenericContainer, PullPolicy } from 'testcontainers';
// Always pull latest image
const container = await new GenericContainer('myapp:latest')
.withPullPolicy(PullPolicy.alwaysPull())
.start();
// Use default policy (pull if not present)
const cached = await new GenericContainer('redis:7-alpine')
.withPullPolicy(PullPolicy.defaultPolicy())
.start();Retry logic for operations that may fail temporarily.
/**
* Interface for retry strategies
*/
interface Retry {
/**
* Retry an operation until predicate passes or timeout
* @param fn - Function to retry
* @param predicate - Function to test result
* @param onTimeout - Function to call on timeout
* @param timeoutMs - Timeout in milliseconds
* @returns Promise resolving to result or timeout value
*/
retryUntil<T, U>(
fn: () => Promise<T>,
predicate: (result: T) => boolean,
onTimeout: () => Promise<U>,
timeoutMs: number
): Promise<T | U>;
}
/**
* Retry strategy with fixed interval between attempts
*/
class IntervalRetry implements Retry {
/**
* Create interval retry strategy
* @param interval - Milliseconds between retry attempts
*/
constructor(interval: number);
retryUntil<T, U>(
fn: () => Promise<T>,
predicate: (result: T) => boolean,
onTimeout: () => Promise<U>,
timeoutMs: number
): Promise<T | U>;
}Usage Example:
import { IntervalRetry } from 'testcontainers';
const retry = new IntervalRetry(1000); // Retry every 1 second
const result = await retry.retryUntil(
async () => {
const response = await fetch('http://localhost:3000/health');
return response.status;
},
(status) => status === 200,
async () => {
throw new Error('Health check timeout');
},
30000 // 30 second timeout
);UUID generation for unique identifiers.
/**
* Interface for UUID generators
*/
interface Uuid {
/**
* Generate next UUID
* @returns UUID string
*/
nextUuid(): string;
}
/**
* Random UUID generator
*/
class RandomUuid implements Uuid {
/**
* Generate random UUID
* @returns Random UUID string
*/
nextUuid(): string;
}
/**
* Generate a random UUID
* @returns Random UUID string
*/
function randomUuid(): string;Usage Example:
import { randomUuid, RandomUuid } from 'testcontainers';
// Simple UUID generation
const id1 = randomUuid();
console.log(id1); // e.g., '123e4567-e89b-12d3-a456-426614174000'
// Using UUID generator instance
const generator = new RandomUuid();
const id2 = generator.nextUuid();
const id3 = generator.nextUuid();Logging utility with namespace support.
/**
* Logger with namespace and level support
*/
class Logger {
/**
* Create logger with namespace
* @param namespace - Logger namespace for filtering
* @param showLevel - Whether to show log level in output
*/
constructor(namespace: string, showLevel?: boolean);
/**
* Check if logging is enabled for this logger
* @returns True if enabled
*/
enabled(): boolean;
/**
* Log trace message
* @param message - Message to log
* @param options - Additional options
*/
trace(message: string, options?: LogOptions): void;
/**
* Log debug message
* @param message - Message to log
* @param options - Additional options
*/
debug(message: string, options?: LogOptions): void;
/**
* Log info message
* @param message - Message to log
* @param options - Additional options
*/
info(message: string, options?: LogOptions): void;
/**
* Log warning message
* @param message - Message to log
* @param options - Additional options
*/
warn(message: string, options?: LogOptions): void;
/**
* Log error message
* @param message - Message to log
* @param options - Additional options
*/
error(message: string, options?: LogOptions): void;
}
/**
* Default logger instance for testcontainers
*/
const log: Logger;
/**
* Specialized logger instances for different namespaces
* Note: These are NOT re-exported from the main 'testcontainers' package.
* They are used internally but documented here for reference.
*/
const buildLog: Logger;
const composeLog: Logger;
const containerLog: Logger;
const execLog: Logger;
const pullLog: Logger;
interface LogOptions {
[key: string]: any;
}Usage Example:
import { log, Logger } from 'testcontainers';
// Use default logger
if (log.enabled()) {
log.info('Starting container');
log.debug('Container configuration', { image: 'redis:7', port: 6379 });
}
// Create custom logger with namespace
const myLogger = new Logger('my-test-suite', true);
myLogger.info('Test starting');
myLogger.error('Test failed', { reason: 'Connection timeout' });
// Enable logging via DEBUG environment variable
// DEBUG=testcontainers:* npm test (all testcontainers logs)
// DEBUG=testcontainers:build npm test (internal build logs)
// DEBUG=testcontainers:pull npm test (internal pull logs)
// DEBUG=testcontainers:containers npm test (internal container logs)Access the Ryuk reaper for automatic cleanup.
/**
* Get or create the Ryuk reaper container
* The reaper automatically removes containers when tests complete
* @param client - Container runtime client
* @returns Promise resolving to reaper instance
*/
function getReaper(client: ContainerRuntimeClient): Promise<Reaper>;
interface Reaper {
// Internal implementation - typically not used directly
}Socat container for port forwarding and tunneling.
/**
* Socat container for port forwarding
*/
class SocatContainer extends GenericContainer {
/**
* Create socat container
* @param image - Socat image (default: 'alpine/socat:1.7.4.3-r0')
*/
constructor(image?: string);
/**
* Configure forwarding target
* @param exposePort - Port to expose on host
* @param host - Target host
* @param internalPort - Target port (default: same as exposePort)
* @returns This container for chaining
*/
withTarget(exposePort: number, host: string, internalPort?: number): this;
/**
* Start socat container
* @returns Promise resolving to started socat container
*/
start(): Promise<StartedSocatContainer>;
}
/**
* Started socat container
*/
class StartedSocatContainer extends AbstractStartedContainer {
// All methods from StartedTestContainer
}Usage Example:
import { SocatContainer } from 'testcontainers';
// Forward port from container to external service
const socat = await new SocatContainer()
.withTarget(8080, 'external-api.example.com', 443)
.start();
// Now containers can access external-api.example.com:443 via socat:8080
const port = socat.getMappedPort(8080);
console.log(`Tunnel available at localhost:${port}`);/**
* Label for testcontainers session ID
*/
const LABEL_TESTCONTAINERS_SESSION_ID = 'org.testcontainers.session-id';Usage Example:
import { GenericContainer, LABEL_TESTCONTAINERS_SESSION_ID } from 'testcontainers';
const container = await new GenericContainer('redis:7-alpine')
.withLabels({
[LABEL_TESTCONTAINERS_SESSION_ID]: 'my-test-session',
'custom-label': 'value'
})
.start();
const labels = container.getLabels();
console.log('Session ID:', labels[LABEL_TESTCONTAINERS_SESSION_ID]);