or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-testcontainers--postgresql

PostgreSQL module for Testcontainers that provides ephemeral database containers for automated testing

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/@testcontainers/postgresql@11.9.x

To install, run

npx @tessl/cli install tessl/npm-testcontainers--postgresql@11.9.0

index.mddocs/

@testcontainers/postgresql

PostgreSQL module for Testcontainers that provides ephemeral PostgreSQL database containers for automated testing. This module enables developers to programmatically create and manage isolated PostgreSQL instances with health checks, wait strategies, connection management, and database snapshot capabilities.

Package Information

  • Package Name: @testcontainers/postgresql
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install @testcontainers/postgresql --save-dev

Core Imports

import { PostgreSqlContainer, StartedPostgreSqlContainer } from '@testcontainers/postgresql';

CommonJS:

const { PostgreSqlContainer, StartedPostgreSqlContainer } = require('@testcontainers/postgresql');

Basic Usage

import { PostgreSqlContainer } from '@testcontainers/postgresql';
import { Client } from 'pg';

// Start a PostgreSQL container
await using container = await new PostgreSqlContainer('postgres:16-alpine').start();

// Connect using individual properties
const client = new Client({
  host: container.getHost(),
  port: container.getPort(),
  database: container.getDatabase(),
  user: container.getUsername(),
  password: container.getPassword(),
});
await client.connect();

// Or connect using connection URI
const client2 = new Client({
  connectionString: container.getConnectionUri(),
});
await client2.connect();

// Run queries
const result = await client.query('SELECT NOW()');
console.log(result.rows[0]);

await client.end();
// Container automatically stops when leaving scope

Capabilities

Container Creation and Configuration

Create and configure a PostgreSQL test container with database credentials and container options.

class PostgreSqlContainer extends GenericContainer {
  constructor(image: string);

  /**
   * Sets the database name
   * @param database - The name of the database to create (default: "test")
   * @returns this (for method chaining)
   */
  withDatabase(database: string): this;

  /**
   * Sets the database username
   * @param username - The username for database access (default: "test")
   * @returns this (for method chaining)
   */
  withUsername(username: string): this;

  /**
   * Sets the database password
   * @param password - The password for database access (default: "test")
   * @returns this (for method chaining)
   */
  withPassword(password: string): this;

  /**
   * Starts the container with configured settings
   * @returns Promise resolving to a StartedPostgreSqlContainer instance
   */
  start(): Promise<StartedPostgreSqlContainer>;
}

Usage Examples:

import { PostgreSqlContainer } from '@testcontainers/postgresql';

// Basic container with defaults
const container = await new PostgreSqlContainer('postgres:16-alpine').start();

// Custom configuration
const container = await new PostgreSqlContainer('postgres:16-alpine')
  .withDatabase('mydb')
  .withUsername('myuser')
  .withPassword('mypassword')
  .start();

// Using PostGIS extension
const postgisContainer = await new PostgreSqlContainer('postgis/postgis:16-3.4')
  .withDatabase('spatial_db')
  .start();

// Using pgvector extension
const vectorContainer = await new PostgreSqlContainer('pgvector/pgvector:pg16')
  .start();

// Using TimescaleDB
const timescaleContainer = await new PostgreSqlContainer('timescale/timescaledb:latest-pg16')
  .start();

Connection Information

Retrieve connection details from a started PostgreSQL container.

class StartedPostgreSqlContainer extends AbstractStartedContainer {
  /**
   * Returns the mapped host port for PostgreSQL
   * @returns The host port mapped to container's port 5432
   */
  getPort(): number;

  /**
   * Returns the configured database name
   * @returns The database name
   */
  getDatabase(): string;

  /**
   * Returns the configured username
   * @returns The database username
   */
  getUsername(): string;

  /**
   * Returns the configured password
   * @returns The database password
   */
  getPassword(): string;

  /**
   * Returns a formatted PostgreSQL connection URI
   * @returns A connection URI in the form: postgres://username:password@host:port/database
   */
  getConnectionUri(): string;
}

Usage Examples:

import { PostgreSqlContainer } from '@testcontainers/postgresql';
import { Client } from 'pg';

await using container = await new PostgreSqlContainer('postgres:16-alpine').start();

// Connect using individual properties
const config = {
  host: container.getHost(),
  port: container.getPort(),
  database: container.getDatabase(),
  user: container.getUsername(),
  password: container.getPassword(),
};
const client = new Client(config);
await client.connect();

// Or use connection URI
const connectionString = container.getConnectionUri();
console.log(connectionString); // postgres://test:test@localhost:32768/test
const client2 = new Client({ connectionString });
await client2.connect();

Database Snapshots

Create and restore database snapshots for efficient test state management.

class StartedPostgreSqlContainer extends AbstractStartedContainer {
  /**
   * Sets the default name to be used for database snapshots
   * @param snapshotName - The name to use for snapshots (default: "migrated_template")
   * @returns this (for method chaining)
   */
  withSnapshotName(snapshotName: string): this;

  /**
   * Creates a snapshot of the current database state as a template
   * @param snapshotName - Name for the snapshot (optional, uses default if not specified)
   * @returns Promise resolving when snapshot is complete
   * @throws Error if attempting to snapshot the postgres system database or if using the same name as the database
   */
  snapshot(snapshotName?: string): Promise<void>;

  /**
   * Restores the database to a specific snapshot
   * @param snapshotName - Name of the snapshot to restore from (optional, uses default if not specified)
   * @returns Promise resolving when restore is complete
   * @throws Error if attempting to restore the postgres system database or if using the same name as the database
   */
  restoreSnapshot(snapshotName?: string): Promise<void>;
}

Important Notes:

  • Cannot use snapshots when the database is set to "postgres" (system database)
  • Snapshot name must be different from the database name
  • Database clients must disconnect before taking or restoring snapshots
  • Default snapshot name is "migrated_template" unless set with withSnapshotName()

Usage Examples:

import { PostgreSqlContainer } from '@testcontainers/postgresql';
import { Client } from 'pg';

await using container = await new PostgreSqlContainer('postgres:16-alpine').start();

let client = new Client({ connectionString: container.getConnectionUri() });
await client.connect();

// Create initial data
await client.query('CREATE TABLE users (id SERIAL PRIMARY KEY, name TEXT)');
await client.query("INSERT INTO users (name) VALUES ('Alice')");

// Must disconnect before snapshot
await client.end();

// Take a snapshot
await container.snapshot();

// Reconnect and modify database
client = new Client({ connectionString: container.getConnectionUri() });
await client.connect();
await client.query("INSERT INTO users (name) VALUES ('Bob')");

// Verify both users exist
let result = await client.query('SELECT * FROM users');
console.log(result.rows.length); // 2

// Must disconnect before restore
await client.end();

// Restore to snapshot
await container.restoreSnapshot();

// Reconnect and verify only initial data exists
client = new Client({ connectionString: container.getConnectionUri() });
await client.connect();
result = await client.query('SELECT * FROM users');
console.log(result.rows.length); // 1 (only Alice)

await client.end();

Using Custom Snapshot Names:

await using container = await new PostgreSqlContainer('postgres:16-alpine').start();

// Set default snapshot name
container.withSnapshotName('my_custom_snapshot');

// Or specify name explicitly
await container.snapshot('snapshot1');
await container.snapshot('snapshot2');

// Restore specific snapshot
await container.restoreSnapshot('snapshot1');

Container Lifecycle

Manage the lifecycle of a started PostgreSQL container.

class StartedPostgreSqlContainer extends AbstractStartedContainer {
  /**
   * Stops the container
   * @param options - Optional stop configuration
   * @returns Promise resolving to a stopped container
   */
  stop(options?: Partial<StopOptions>): Promise<StoppedTestContainer>;

  /**
   * Restarts the container
   * @param options - Optional restart configuration
   * @returns Promise resolving when restart is complete
   */
  restart(options?: Partial<RestartOptions>): Promise<void>;

  /**
   * Commits the container to a new image
   * @param options - Commit configuration options
   * @returns Promise resolving to the new image ID
   */
  commit(options: CommitOptions): Promise<string>;

  /**
   * Async disposal support for use with 'await using' syntax
   * @returns Promise resolving when container is stopped and cleaned up
   */
  [Symbol.asyncDispose](): Promise<void>;
}

Usage Examples:

import { PostgreSqlContainer } from '@testcontainers/postgresql';

// Automatic cleanup with async disposal
await using container = await new PostgreSqlContainer('postgres:16-alpine').start();
// Container automatically stopped when leaving scope

// Manual lifecycle management
const container2 = await new PostgreSqlContainer('postgres:16-alpine').start();

// Restart container
await container2.restart();

// Stop manually
await container2.stop();

Container Information

Retrieve metadata and configuration from a started PostgreSQL container.

class StartedPostgreSqlContainer extends AbstractStartedContainer {
  /**
   * Returns the host where the container is running
   * @returns The container host (typically 'localhost')
   */
  getHost(): string;

  /**
   * Returns the container hostname
   * @returns The container's hostname
   */
  getHostname(): string;

  /**
   * Returns the container name
   * @returns The container name
   */
  getName(): string;

  /**
   * Returns the container ID
   * @returns The Docker container ID
   */
  getId(): string;

  /**
   * Returns the container labels
   * @returns Object containing container labels
   */
  getLabels(): Labels;

  /**
   * Returns the first mapped port
   * @returns The first exposed port mapping
   */
  getFirstMappedPort(): number;

  /**
   * Returns a specific mapped port
   * @param port - The container port number
   * @param protocol - Optional protocol ('tcp' or 'udp', default: 'tcp')
   * @returns The host port mapped to the container port
   */
  getMappedPort(port: number, protocol?: string): number;
}

Network Information

Access network configuration and IP addresses for a started PostgreSQL container.

class StartedPostgreSqlContainer extends AbstractStartedContainer {
  /**
   * Returns the list of networks the container is connected to
   * @returns Array of network names
   */
  getNetworkNames(): string[];

  /**
   * Returns the network ID for a specific network name
   * @param networkName - The name of the network
   * @returns The network ID
   */
  getNetworkId(networkName: string): string;

  /**
   * Returns the container's IP address in a specific network
   * @param networkName - The name of the network
   * @returns The IP address
   */
  getIpAddress(networkName: string): string;
}

File Operations

Copy files and directories to or from a running PostgreSQL container.

class StartedPostgreSqlContainer extends AbstractStartedContainer {
  /**
   * Copies files to the running container
   * @param filesToCopy - Array of file copy specifications
   * @returns Promise resolving when copy is complete
   */
  copyFilesToContainer(filesToCopy: FileToCopy[]): Promise<void>;

  /**
   * Copies directories to the running container
   * @param directoriesToCopy - Array of directory copy specifications
   * @returns Promise resolving when copy is complete
   */
  copyDirectoriesToContainer(directoriesToCopy: DirectoryToCopy[]): Promise<void>;

  /**
   * Copies content to the running container
   * @param contentsToCopy - Array of content copy specifications
   * @returns Promise resolving when copy is complete
   */
  copyContentToContainer(contentsToCopy: ContentToCopy[]): Promise<void>;

  /**
   * Copies an archive to the running container
   * @param tar - Readable stream containing tar archive
   * @param target - Optional target path in container
   * @returns Promise resolving when copy is complete
   */
  copyArchiveToContainer(tar: Readable, target?: string): Promise<void>;

  /**
   * Copies an archive from the running container
   * @param path - Path in container to copy from
   * @returns Promise resolving to a readable stream of the tar archive
   */
  copyArchiveFromContainer(path: string): Promise<NodeJS.ReadableStream>;
}

Container Execution

Execute commands and retrieve logs from a running PostgreSQL container.

class StartedPostgreSqlContainer extends AbstractStartedContainer {
  /**
   * Executes a command in the running container
   * @param command - Command string or array of command parts
   * @param opts - Optional execution configuration
   * @returns Promise resolving to execution result with exit code and output
   */
  exec(command: string | string[], opts?: Partial<ExecOptions>): Promise<ExecResult>;

  /**
   * Retrieves container logs
   * @param opts - Optional log configuration (since timestamp, tail count)
   * @returns Promise resolving to a readable stream of logs
   */
  logs(opts?: { since?: number; tail?: number }): Promise<Readable>;
}

Usage Examples:

import { PostgreSqlContainer } from '@testcontainers/postgresql';

await using container = await new PostgreSqlContainer('postgres:16-alpine').start();

// Execute command in container
const result = await container.exec(['psql', '--version']);
console.log(result.output);
console.log(result.exitCode);

// Get container logs
const logStream = await container.logs({ tail: 100 });
logStream.on('data', (chunk) => console.log(chunk.toString()));

Advanced Container Configuration

PostgreSqlContainer inherits additional configuration methods from GenericContainer for advanced use cases.

class PostgreSqlContainer extends GenericContainer {
  /**
   * Sets environment variables for the container
   * @param environment - Object with environment variable key-value pairs
   * @returns this (for method chaining)
   */
  withEnvironment(environment: Environment): this;

  /**
   * Configures additional exposed ports
   * @param ports - Port numbers or port bindings to expose
   * @returns this (for method chaining)
   */
  withExposedPorts(...ports: PortWithOptionalBinding[]): this;

  /**
   * Connects the container to a specific network
   * @param network - The network to connect to
   * @returns this (for method chaining)
   */
  withNetwork(network: StartedNetwork): this;

  /**
   * Sets the network mode for the container
   * @param networkMode - Network mode ('bridge', 'host', 'none', or container ID)
   * @returns this (for method chaining)
   */
  withNetworkMode(networkMode: string): this;

  /**
   * Adds network aliases for the container
   * @param networkAliases - Network alias names
   * @returns this (for method chaining)
   */
  withNetworkAliases(...networkAliases: string[]): this;

  /**
   * Configures health check for the container
   * @param healthCheck - Health check configuration
   * @returns this (for method chaining)
   */
  withHealthCheck(healthCheck: HealthCheck): this;

  /**
   * Sets the startup timeout in milliseconds
   * @param startupTimeoutMs - Timeout in milliseconds (default: 120000)
   * @returns this (for method chaining)
   */
  withStartupTimeout(startupTimeoutMs: number): this;

  /**
   * Sets the wait strategy for container readiness
   * @param waitStrategy - Wait strategy to use
   * @returns this (for method chaining)
   */
  withWaitStrategy(waitStrategy: WaitStrategy): this;

  /**
   * Configures bind mounts for the container
   * @param bindMounts - Array of bind mount configurations
   * @returns this (for method chaining)
   */
  withBindMounts(bindMounts: BindMount[]): this;

  /**
   * Copies files to the container before starting
   * @param filesToCopy - Array of file copy specifications
   * @returns this (for method chaining)
   */
  withCopyFilesToContainer(filesToCopy: FileToCopy[]): this;

  /**
   * Copies directories to the container before starting
   * @param directoriesToCopy - Array of directory copy specifications
   * @returns this (for method chaining)
   */
  withCopyDirectoriesToContainer(directoriesToCopy: DirectoryToCopy[]): this;

  /**
   * Copies content to the container before starting
   * @param contentsToCopy - Array of content copy specifications
   * @returns this (for method chaining)
   */
  withCopyContentToContainer(contentsToCopy: ContentToCopy[]): this;

  /**
   * Sets the container name
   * @param name - Container name
   * @returns this (for method chaining)
   */
  withName(name: string): this;

  /**
   * Adds labels to the container
   * @param labels - Object with label key-value pairs
   * @returns this (for method chaining)
   */
  withLabels(labels: Labels): this;

  /**
   * Sets the container command
   * @param command - Array of command parts
   * @returns this (for method chaining)
   */
  withCommand(command: string[]): this;

  /**
   * Sets the container entrypoint
   * @param entrypoint - Array of entrypoint parts
   * @returns this (for method chaining)
   */
  withEntrypoint(entrypoint: string[]): this;

  /**
   * Sets the working directory in the container
   * @param workingDir - Working directory path
   * @returns this (for method chaining)
   */
  withWorkingDir(workingDir: string): this;

  /**
   * Sets the user for the container
   * @param user - User name or UID
   * @returns this (for method chaining)
   */
  withUser(user: string): this;

  /**
   * Enables container reuse between test runs
   * @returns this (for method chaining)
   */
  withReuse(): this;

  /**
   * Configures auto-removal of container on stop
   * @param autoRemove - Whether to auto-remove (default: true)
   * @returns this (for method chaining)
   */
  withAutoRemove(autoRemove: boolean): this;

  /**
   * Sets the image pull policy
   * @param pullPolicy - Pull policy ('always', 'never', or 'default')
   * @returns this (for method chaining)
   */
  withPullPolicy(pullPolicy: ImagePullPolicy): this;

  /**
   * Runs the container in privileged mode
   * @returns this (for method chaining)
   */
  withPrivilegedMode(): this;

  /**
   * Configures resource limits (CPU and memory)
   * @param quota - Resource quota configuration
   * @returns this (for method chaining)
   */
  withResourcesQuota(quota: ResourcesQuota): this;

  /**
   * Sets shared memory size for the container
   * @param bytes - Size in bytes
   * @returns this (for method chaining)
   */
  withSharedMemorySize(bytes: number): this;

  /**
   * Attaches a log consumer to the container
   * @param logConsumer - Function to consume log stream
   * @returns this (for method chaining)
   */
  withLogConsumer(logConsumer: (stream: Readable) => unknown): this;

  /**
   * Sets the platform for the container
   * @param platform - Platform string (e.g., 'linux/amd64')
   * @returns this (for method chaining)
   */
  withPlatform(platform: string): this;

  /**
   * Sets the hostname for the container
   * @param hostname - Hostname
   * @returns this (for method chaining)
   */
  withHostname(hostname: string): this;

  /**
   * Configures temporary file systems
   * @param tmpFs - Temporary filesystem configuration
   * @returns this (for method chaining)
   */
  withTmpFs(tmpFs: TmpFs): this;

  /**
   * Configures resource limits
   * @param ulimits - Resource limit configuration
   * @returns this (for method chaining)
   */
  withUlimits(ulimits: Ulimits): this;

  /**
   * Adds Linux capabilities to the container
   * @param capabilities - Capability names to add
   * @returns this (for method chaining)
   */
  withAddedCapabilities(...capabilities: string[]): this;

  /**
   * Drops Linux capabilities from the container
   * @param capabilities - Capability names to drop
   * @returns this (for method chaining)
   */
  withDroppedCapabilities(...capabilities: string[]): this;

  /**
   * Adds extra host entries to the container
   * @param extraHosts - Array of host entry configurations
   * @returns this (for method chaining)
   */
  withExtraHosts(extraHosts: ExtraHost[]): this;

  /**
   * Uses the default Docker log driver
   * @returns this (for method chaining)
   */
  withDefaultLogDriver(): this;

  /**
   * Sets the IPC mode for the container
   * @param ipcMode - IPC mode ('host', 'private', 'shareable', or container ID)
   * @returns this (for method chaining)
   */
  withIpcMode(ipcMode: string): this;
}

Types

All types are defined in the parent testcontainers package:

// From testcontainers package
type Environment = { [key: string]: string };
type Labels = { [key: string]: string };
type PortWithOptionalBinding = number | { container: number; host: number };
type ImagePullPolicy = 'always' | 'never' | 'default';

interface StartedNetwork {
  getName(): string;
  getId(): string;
}

interface BindMount {
  source: string;
  target: string;
  mode?: 'ro' | 'rw';
}

interface FileToCopy {
  source: string;
  target: string;
}

interface DirectoryToCopy {
  source: string;
  target: string;
}

interface ContentToCopy {
  content: string;
  target: string;
}

interface HealthCheck {
  test: string[];
  interval?: number;
  timeout?: number;
  retries?: number;
  startPeriod?: number;
}

interface ResourcesQuota {
  memory?: number;
  cpu?: number;
}

interface TmpFs {
  [path: string]: string;
}

interface Ulimits {
  [name: string]: { soft: number; hard: number };
}

interface ExtraHost {
  host: string;
  ipAddress: string;
}

interface StopOptions {
  timeout?: number;
  remove?: boolean;
}

interface RestartOptions {
  timeout?: number;
}

interface CommitOptions {
  repository: string;
  tag?: string;
  comment?: string;
  author?: string;
  pause?: boolean;
  changes?: string[];
}

interface ExecOptions {
  workingDir?: string;
  env?: Environment;
  user?: string;
  privileged?: boolean;
}

interface ExecResult {
  output: string;
  exitCode: number;
}

// Node.js types
interface Readable extends NodeJS.ReadableStream {}

Error Handling

The module throws errors in the following scenarios:

Snapshot Errors:

  • Attempting to use snapshots with the "postgres" system database
  • Using a snapshot name that matches the database name
  • SQL command execution failures during snapshot/restore operations

Container Errors:

  • Container startup timeout (default 120 seconds)
  • Health check failures
  • Network configuration errors
  • Invalid Docker image names

Connection Errors:

  • Port mapping failures
  • Network connectivity issues

All errors are thrown as standard JavaScript Error objects with descriptive messages.

Supported PostgreSQL Images

This module works with any PostgreSQL-compatible Docker image:

Official PostgreSQL:

new PostgreSqlContainer('postgres:16-alpine')
new PostgreSqlContainer('postgres:15')
new PostgreSqlContainer('postgres:14')

PostGIS (spatial extension):

new PostgreSqlContainer('postgis/postgis:16-3.4')
new PostgreSqlContainer('postgis/postgis:15-3.3')

pgvector (vector similarity search):

new PostgreSqlContainer('pgvector/pgvector:pg16')
new PostgreSqlContainer('pgvector/pgvector:pg15')

TimescaleDB (time-series extension):

new PostgreSqlContainer('timescale/timescaledb:latest-pg16')
new PostgreSqlContainer('timescale/timescaledb:latest-pg15')

Implementation Notes

Default Configuration:

  • PostgreSQL port 5432 is automatically exposed
  • Default database name: "test"
  • Default username: "test"
  • Default password: "test"
  • Startup timeout: 120,000ms (2 minutes)

Health Checks:

  • Automatically configured using pg_isready command
  • Uses configured credentials for health check
  • Combined with listening ports wait strategy
  • Interval: 250ms, Timeout: 1000ms, Retries: 1000

Environment Variables:

  • POSTGRES_DB - Set from withDatabase()
  • POSTGRES_USER - Set from withUsername()
  • POSTGRES_PASSWORD - Set from withPassword()

Snapshot Implementation:

  • Creates template databases using PostgreSQL's CREATE DATABASE ... WITH TEMPLATE command
  • Marks snapshots as template databases (is_template = TRUE)
  • Restore drops and recreates the target database from the template
  • Uses DROP DATABASE ... WITH (FORCE) for forced disconnect during restore