testcontainers-node
Spin up disposable Docker containers to run real databases, brokers, and browsers in your Node.js tests.
Repository Health
Technical Analysis
Testcontainers is the Node.js port of the Testcontainers family of libraries, giving test suites throwaway Docker containers instead of mocks, in-memory fakes, or shared test environments. A test can start a real PostgreSQL instance, a Kafka broker, or a headless Chrome browser, run against it, and let the library tear the container down automatically when the test process exits — no leftover state, no manually managed docker-compose files.
The core testcontainers package exposes a GenericContainer builder for arbitrary images alongside lower-level primitives for networks, port waiting, log-based readiness checks, and Docker Compose environments. On top of that, the monorepo ships 40+ purpose-built modules (@testcontainers/postgresql, @testcontainers/kafka, @testcontainers/localstack, @testcontainers/mongodb, and more) that wrap common services with sensible defaults and typed convenience APIs, so most projects only need to import the module for the service they’re testing against.
A background reaper (Ryuk) container tracks every container and network a test session creates and forcibly removes them if the test process crashes or is killed, so CI runners don’t accumulate orphaned containers. Combined with pluggable wait strategies (port, log line, HTTP endpoint, health check, shell command) and support for reusable containers across test files, it’s built specifically for integration and end-to-end testing scenarios where mocking the real dependency isn’t good enough.
What You Get
- A
GenericContainerbuilder for launching any Docker image with custom commands, entrypoints, environment variables, bind mounts, and resource limits - 40+ pre-built service modules (PostgreSQL, MySQL, MongoDB, Kafka, Redis, LocalStack, Elasticsearch, Selenium, and more) with typed, service-specific convenience APIs
- Pluggable wait strategies — port availability, log-line matching, HTTP endpoint polling, Docker health checks, or a custom shell command — to know precisely when a container is ready
- A Docker Compose environment wrapper for spinning up a full multi-container
docker-compose.ymlstack per test run - An automatic reaper (Ryuk) container that guarantees cleanup of containers and networks even if the test process is killed or crashes
- Support for container reuse across test files/runs to avoid repeatedly paying startup cost during local development
Common Use Cases
- Running integration tests against a real PostgreSQL/MySQL/MongoDB instance instead of an in-memory or mocked database
- Testing message-driven services end-to-end against a real Kafka, RabbitMQ, or NATS broker
- Running browser automation tests against a containerized Selenium/Chrome instance in CI without installing browsers on the runner
- Verifying application behavior against cloud-service emulators (LocalStack for AWS, Azurite for Azure Storage) without hitting real cloud accounts
- Spinning up an entire application stack via Docker Compose for full end-to-end test scenarios
Under The Hood
Architecture
The library is organized around a small set of composable layers under packages/testcontainers/src: container-runtime resolves and talks to the local Docker daemon (via dockerode, with pluggable connection strategies for Unix sockets, rootless Docker, npipe on Windows, and a TESTCONTAINERS_HOST override), generic-container is the public builder API that assembles a ContainerCreateOptions/HostConfig payload and delegates to that runtime client, wait-strategies decouples “container started” from “container ready” behind a common WaitStrategy interface (composable via composite-wait-strategy.ts), and a standalone reaper module (reaper.ts) runs a sidecar Ryuk container that tracks every session’s containers/networks by Docker label and force-removes them on session end, so cleanup doesn’t depend on the test process itself staying alive. Docker Compose support (docker-compose-environment) and networking (network.ts) are layered on the same runtime client rather than duplicating Docker access logic, and 42 independent modules under packages/modules/* extend GenericContainer per service without touching the core.
Tech Stack
Written entirely in TypeScript on Node.js 22+, using dockerode for the Docker Engine API, archiver/tar-fs for building copy-to-container archives, async-lock for guarding concurrent container-reuse creation, undici for HTTP-based wait strategies, and ssh-remote-port-forward for the port-forwarder module that exposes host services to containers. The repo is an npm workspaces monorepo (packages/testcontainers plus packages/modules/*), built with tsc, linted with a flat ESLint config plus typescript-eslint, and formatted with Prettier including import sorting.
Code Quality
Testing is extensive and treated as a first-class concern (fitting, given the library’s purpose): 62 *.test.ts files sit alongside roughly 90 source files, run via Vitest with global mock reset/restore between tests, CI retries for flaky Docker-in-Docker runs, and concurrent execution enabled. Errors are handled explicitly and typed throughout (e.g. error instanceof Error ? error.message : String(error) patterns rather than swallowing), and CI (checks.yml) only runs the modules actually touched by a change via a git diff-based detection step, alongside a separate CodeQL security-analysis workflow and a dependency-review workflow gating new dependencies on pull requests.
What Makes It Unique Unlike most Node.js test-mocking libraries, testcontainers-node doesn’t simulate a dependency — it manages the real, upstream Docker image for it, with a reaper process specifically designed to guarantee cleanup even under abnormal test-runner termination (crashed process, killed CI job), which is a harder problem than most testing libraries attempt to solve. Its wait-strategy abstraction and 40+-module ecosystem also mean most common test dependencies (databases, queues, cloud emulators, browsers) already have a maintained, typed wrapper rather than requiring hand-rolled container configuration.
Used by 32 apps in this directory
Budibase
Low Code Platforms · No Code Platforms
Build AI agents, automations, and internal apps on a single open-source platform with full self-hosting control.
ChartBrew
Analytics · Databases
Open-source reporting platform to build live dashboards from SQL, NoSQL, APIs, and SaaS tools with an AI assistant that creates charts from natural language.
Colanode
Knowledge Management · Team Chat · Collaboration
Local-first, self-hosted workspace that combines real-time chat, Notion-style pages, and structured databases — all synced via CRDTs so you work offline without losing a keystroke.
Colanode
Knowledge Management · Team Chat · Collaboration
Local-first, self-hosted workspace that combines real-time chat, Notion-style pages, and structured databases — all synced via CRDTs so you work offline without losing a keystroke.
Colanode
Knowledge Management · Team Chat · Collaboration
Local-first, self-hosted workspace that combines real-time chat, Notion-style pages, and structured databases — all synced via CRDTs so you work offline without losing a keystroke.
Element Web
Team Chat · Collaboration
A polished, self-hostable Matrix client for secure, decentralized messaging and collaboration that puts your organization in full control of its data.
Element Web
Team Chat · Collaboration
A polished, self-hostable Matrix client for secure, decentralized messaging and collaboration that puts your organization in full control of its data.
Jitsi Meet
Team Chat · Collaboration · Video Conferencing
Open-source, end-to-end encrypted video conferencing you can self-host or embed into any web or mobile app.
Jitsu
Data Engineering
Open-source, fully-scriptable data ingestion engine that streams events from web, apps, and APIs to any data warehouse in real time.