Self-hosted service
testcontainers/testcontainers-node avatar
testcontainers/testcontainers-node

testcontainers-node: real databases in Node tests without installing them

Testcontainers is a NodeJS library that supports tests, providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container.

2,625 stars274 forksTypeScriptMIT

At a glance

What is it?
The Node port of Testcontainers starts throwaway containers for your test suite so a Postgres or Redis dependency behaves like the real thing. The repository is a workspace of TypeScript packages with a README that is five badges and a documentation link.
Who is it for?
testcontainers-node earns its place in a suite that needs a genuine Postgres, Redis or browser rather than a hand-written fake, and it is a poor fit for anything that must stay fast and hermetic. GitHub reports the last push on 2026-09-23 with v12.1.0 published 2026-08-04, so the version line is moving.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 10, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A monorepo of container modules behind a five badge README

The README for this repository is short enough to read in under a minute. It carries the GitHub Codespaces badge, the checks badge, two npm badges for the `testcontainers` package, a link to the documentation site at node.testcontainers.org, a licence line, a copyright line reading 2018 to 2025 for Cristian Greco and other authors, and a footer pointing at the Slack workspace, the Java Testcontainers project and Testcontainers Cloud. There is no installation snippet, no example and no API listing in the file.

That is not an omission so much as a division of labour. Usage documentation lives on the documentation site, and the repository holds the implementation. What the repository shows you is the shape of the implementation, which is where the interesting decisions sit. GitHub reports the project as TypeScript, MIT licensed, on the `main` branch, last pushed 2026-09-23, with releases v12.1.0 on 2026-08-04, v12.0.4 on 2026-06-29 and v12.0.3 on 2026-06-17.

The copyright line is worth pausing on. It stops at 2025 while the release history and the push date are both in 2026, which tells you the line was not updated with the 2026 work. Nothing about the package depends on that line, but it is a fair signal that the README in this repository is maintained by a lighter touch than the code is.

Workspaces, a Node floor of 22.22, and a vitest suite

`package.json` describes the whole thing as one npm workspace called `testcontainers-monorepo`, with workspace globs for `packages/testcontainers` and `packages/modules/*`. That single line tells you how to find any feature: the core package holds the container and lifecycle machinery, and each module under `packages/modules/` is a service integration. The repository topics back that reading, listing docker, node, testcontainers and testing.

The engines field asks for `node` `>= 22.22`. That is a higher floor than most Node libraries state, and it is enforced in practice by a dedicated check script: `check-engines:root` and `check-engines:testcontainers` both shell out to `ls-engines` in ideal mode, so a Node version below the floor is a build failure rather than a runtime surprise. Read the floor before you decide the library fits your CI image.

The three commands you would reach for first:

bash
npm run test
npm run test:ci
npm run check-compiles

`test` runs `vitest run`, and `test:ci` is the same run with coverage flags appended. `check-compiles` is the interesting one: it runs `tsc -b` across `packages/testcontainers packages/modules/*`, a build of every package in the workspace, which is what catches a module whose types have drifted from the core package's.

The documentation site builds in its own container

Docs in this project are MkDocs, and they are served from a container described in `docker-compose.yml` at the repository root. The whole service definition is five keys:

yaml
services:
  docs:
    image: python:3.14
    command: sh -c "pip install -r requirements.txt && mkdocs serve -a 0.0.0.0:8000"
    working_dir: /docs

The pinned requirements in `requirements.txt` are four packages: `mkdocs` at 1.6.1, `mkdocs-material` at 9.7.7, `mkdocs-codeinclude-plugin` at 0.3.1 and `mkdocs-markdownextradata-plugin` at 0.2.6. The code include plugin matters more than it looks, because it lets the documentation pull command examples straight out of module source rather than duplicating them by hand, so the snippets on the site track the code.

The npm script behind this is `docs:serve`, which runs `docker compose up`. Two details are worth copying if you set up your own docs loop: the container runs as root with no user mapping, and the working directory is `/docs` with the repository bind mounted there. The docs tree also contains `mkdocs.yml` at the root, alongside a `docs/` directory that holds the site source. Whether you run this through Docker or a local Python environment is your call, but the container path needs no Python setup at all, which is convenient on a machine that has Node and nothing else.

What a throwaway container actually buys your assertion

The project's one line description says it supports tests by providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container. That is the whole pitch, and it is narrower than the marketing sometimes suggests. You are not getting a mock. You are getting a real Postgres process, started fresh for one test, destroyed afterwards, with a connection URL handed to your code.

The difference matters most in the places where mocks lie. A SQL mock returns the rows you told it to return, so it cannot catch a query that Postgres would reject for a syntax reason, a migration that runs in the wrong order, or a driver that negotiates a protocol badly. A real container can catch all three. It can also catch the case where your code depends on a specific collation, a specific extension, or a specific error message, because the error comes from the real server.

The cost is symmetric and worth being clear about. Every test that needs a container pays container startup, and the README does not document any facility for reusing one container across a suite. GitHub reports no archived state, and the repository is small enough to read: `docs/`, `packages/`, a `docker-compose.yml` for the docs service, `eslint.config.js`, `vitest.config.ts`, `tsconfig.base.json` and `AGENTS.md` at the top level. So the design surface you are buying is thin. You get a lifecycle, a wait strategy and a connection URL, and the rest of the behaviour comes from the image you point it at.

Where the cost sits, and what the README never claims

Two limitations are visible from the repository without opening a single documentation page. The first is the container runtime itself. Every module in `packages/modules/` needs a Docker daemon or an equivalent available to the test process, which on a corporate laptop often means the suite is less portable than the code it tests, and on a CI runner means a service dependency the pipeline has to provide.

The second is the version floor, already mentioned: `node` `>= 22.22`. Projects that still test against an older Node line cannot adopt this without raising their own floor or pinning an older major release of the library.

What the README does not claim is worth recording too, because the omissions are informative. It does not discuss CI providers, does not show a single test file, and does not name a single supported database. If you are choosing between this library and hand-rolled fixtures, the questions that decide it, which image versions are supported, how readiness is detected, how a failed container surfaces its logs, live on the documentation site rather than in the file you land on from GitHub.

There is also a quieter commercial dimension. The footer links Testcontainers Cloud alongside the Java implementation, so the same test code that runs locally against throwaway containers is being pointed at a hosted service. The MIT licence covers the library, which means the package itself is not the thing on trial here, but it does tell you where the project is heading.

Following the package boundary into the docs

Once you accept that the README is a signpost, the repository becomes easy to read. `CONTRIBUTING.md` holds the contribution route, `packages/testcontainers` is where the core lifecycle lives, and `packages/modules/*` is a directory you can enumerate to see what is supported. The presence of `AGENTS.md` at the root suggests the maintainers have written down conventions for automated contributors, which usually means the module interface is described somewhere more formal than a chat message.

The release numbering is the other signal worth reading. Twelve major versions over roughly eight years of published releases is not a fast churn rate, and the recent line, v12.0.3, v12.0.4 and v12.1.0, lands a patch and a minor inside about six weeks. That pattern reads as a stable core with new service modules and engine improvements arriving on top, which is the right shape for a testing library where a breaking change in the middle of a suite is expensive.

So the practical starting point is narrow. Open the module list on node.testcontainers.org, find the service you actually need, read that module's page, and only then decide whether the startup cost is worth it. If the thing you need is not in the module list, the thin README will not tell you whether it is planned; the repository tree and the documentation site are the only two places that answer.

Editorial conclusion

testcontainers-node earns its place in a suite that needs a genuine Postgres, Redis or browser rather than a hand-written fake, and it is a poor fit for anything that must stay fast and hermetic. GitHub reports the last push on 2026-09-23 with v12.1.0 published 2026-08-04, so the version line is moving. Start by reading the module list on node.testcontainers.org for the service you need, then decide from your own numbers how many seconds of container startup your suite can absorb.

Frequently asked questions

What are Testcontainers used for?

For starting real services, such as databases or Selenium web browsers, as throwaway containers so tests exercise the genuine article instead of a fake. In this Node implementation the library handles the container lifecycle and hands your test a connection URL. The per-service integrations live as separate packages under `packages/modules/`.

Do Testcontainers work without Docker?

The repository assumes a container runtime is reachable. Its own documentation service runs through `docker compose up` with `docs:serve`, and each module under `packages/modules/` starts a container, so something Docker compatible has to be available to the test process. The README does not describe a runtime-less fallback.

What Node version does testcontainers-node require?

The `package.json` engines field requires `node` `>= 22.22`, and two scripts named `check-engines:root` and `check-engines:testcontainers` run `ls-engines` to enforce it. A project on an older Node line would have to raise its floor or pin an earlier major release of the library.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. testcontainers/testcontainers-node on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/testcontainers-testcontainers-node.svg)](https://hysenlabs.com/projects/testcontainers-testcontainers-node)