testcontainers / testcontainers/testcontainers-java
[Bug]: GenericContainer.start() and stop() are not thread-safe
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 8.7k
- Forks
- 1.9k
- Avg merge
- 2d 17h
- Merged PRs (30d)
- 9
Description
Module
Core
Testcontainers version
2.0.4
Using the latest Testcontainers version?
Yes
What happened?
GenericContainer.start() guards against double-start with if (containerId != null) return, but start() is not synchronized. When two threads call start() on the same container concurrently, both can pass the guard before either sets containerId, creating two Docker containers for one logical dependency.
This can happen when @Testcontainers is used and the container is also started from another context. For example, custom test infrastructure that handles @Container annotations alongside the JUnit extension:
@Testcontainers
class MyTest {
// Custom infrastructure starts this container during context setup.
// The @Testcontainers extension also starts it via Startables.deepStart().
// Both run concurrently - the second start() should be a no-op, but without
// synchronization both threads pass the containerId == null check.
@Container
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:16");
}
The workaround is to not annotate dependencies with @Container when custom infrastructure already handles them, but this is not obvious to developers and error-prone.
I can't provide the exact scenario because we faced this in a closed-source project. The example above illustrates the general pattern.
Additional Information
I submitted a PR with a fix: #11702
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with GenericContainer.start() and stop(), especially the containerId guard described in the issue. Review PR #11702 and the concurrent @Testcontainers and @Container example; done means concurrent start and stop calls are safe and do not create duplicate containers or mishandle the shared dependency.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- docker, java
- Domain
- testing-qa
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100