Problem
GenericContainer.start() waits for the host port bindings to appear (inspectContainerUntilPortsExposed) before the wait strategy runs. That pre-wait has a hardcoded 10 s budget: the util has timeout = 10_000 as a default parameter, and neither call site in generic-container.ts passes this.startupTimeoutMs. So withStartupTimeout(...) only extends the wait strategy; a container whose port binding takes longer than 10 s fails with
Timed out after 10000ms while waiting for container ports to be bound to the host
no matter what startup timeout the caller configured.
This looks like #1281, but I'd like to add a measured data point that is not Kafka/flaky-environment related — the pre-wait itself is the thing that trips, and only under CPU contention.
Measurements (testcontainers 12.1.0, Node 24.19, Docker 29.x, postgres:18-alpine)
- Local (Apple M3 Pro, one container): host port bound in 1.1–2.6 s.
- Local, six workspace packages each starting one
postgres:18-alpine at the same time (vitest workers): successful starts bound their ports in 2.2–7.2 s; a cold image pull pushed some past 10 s.
- GitHub Actions
ubuntu-latest (2 vCPU, nproc = 2), same six concurrent containers: one start measured 16.7 s until the port was bound — the container was healthy afterwards, it was just slow under load. It failed at 10 s five times in one workflow run although every container had withStartupTimeout(120_000).
So the 10 s default is not "a few milliseconds of Docker Desktop race" in practice: on a loaded host the port binding legitimately takes longer, and the configured startup timeout is the natural budget for it.
Root cause
packages/testcontainers/src/generic-container/generic-container.ts — both calls omit the third argument:
inspectResult = await inspectContainerUntilPortsExposed(() => client.container.inspect(container), container.id); // reuseContainer
const inspectResult = await inspectContainerUntilPortsExposed(
() => client.container.inspect(container),
container.id
); // startContainer
inspect-container-util-ports-exposed.ts: timeout = 10_000.
Proposed fix
Pass this.startupTimeoutMs at both call sites. When withStartupTimeout was never called the value is undefined, so the default parameter still yields 10 s — behaviour only changes for callers who explicitly asked for a longer budget. We run exactly this as a pnpm patch since yesterday; the same suite went from 5 pre-wait timeouts per run to 0. PR follows.
Environment
- testcontainers: 12.1.0 (
latest at the time of writing)
- Node.js: v24.19.0
- Docker: 29.6.1 (Docker Desktop, arm64) locally; GitHub-hosted
ubuntu-latest in CI
Problem
GenericContainer.start()waits for the host port bindings to appear (inspectContainerUntilPortsExposed) before the wait strategy runs. That pre-wait has a hardcoded 10 s budget: the util hastimeout = 10_000as a default parameter, and neither call site ingeneric-container.tspassesthis.startupTimeoutMs. SowithStartupTimeout(...)only extends the wait strategy; a container whose port binding takes longer than 10 s fails withno matter what startup timeout the caller configured.
This looks like #1281, but I'd like to add a measured data point that is not Kafka/flaky-environment related — the pre-wait itself is the thing that trips, and only under CPU contention.
Measurements (testcontainers 12.1.0, Node 24.19, Docker 29.x,
postgres:18-alpine)postgres:18-alpineat the same time (vitest workers): successful starts bound their ports in 2.2–7.2 s; a cold image pull pushed some past 10 s.ubuntu-latest(2 vCPU,nproc= 2), same six concurrent containers: one start measured 16.7 s until the port was bound — the container was healthy afterwards, it was just slow under load. It failed at 10 s five times in one workflow run although every container hadwithStartupTimeout(120_000).So the 10 s default is not "a few milliseconds of Docker Desktop race" in practice: on a loaded host the port binding legitimately takes longer, and the configured startup timeout is the natural budget for it.
Root cause
packages/testcontainers/src/generic-container/generic-container.ts— both calls omit the third argument:inspect-container-util-ports-exposed.ts:timeout = 10_000.Proposed fix
Pass
this.startupTimeoutMsat both call sites. WhenwithStartupTimeoutwas never called the value isundefined, so the default parameter still yields 10 s — behaviour only changes for callers who explicitly asked for a longer budget. We run exactly this as apnpm patchsince yesterday; the same suite went from 5 pre-wait timeouts per run to 0. PR follows.Environment
latestat the time of writing)ubuntu-latestin CI