testcontainers / testcontainers-java

Testcontainers is a Java library that supports JUnit tests, providing lightweight, throwaway instances of common databases, Selenium web browsers, or anything else that can run in a Docker container.
https://testcontainers.org
MIT License
8.05k stars 1.66k forks source link

[Feature]: Container startup attempt backoff strategy #9479

Open Two4 opened 3 weeks ago

Two4 commented 3 weeks ago

Module

None

Problem

I have a JUnit test extension that starts up a container. If multiple tests are executing in parallel in isolated JVMs, they contend for the container name and port bindings. One can work around this by giving it effectively infinite startup attempts and a reasonable startup timeout, but this generates excessive test logs from constant startup attempts.

Solution

Introduce a startup attempt backoff strategy option when constructing a container. Being able to exponentially backoff to a reasonable interval between startup attempts would help in reducing logs.

Benefit

This would benefit any situation where there is contention for exclusive resources between container instances, or any other situation where container startups are very flaky for an extended period, but eventual success is likely.

Alternatives

At the moment I'm using Awaitility to check for container name contention before attempting startup.

Would you like to help contributing this feature?

Yes

eddumelendez commented 2 weeks ago

they contend for the container name and port bindings

Hi, can you elaborate about this please? Testcontainers promotes usage of random ports to be used and connect to the services running inside the container. At the same time, container names are not used by default. Of course, the API allows to do it but not in a easy way in order to avoid port collision.

Two4 commented 2 weeks ago

In this particular case, testcontainers is used to spin up a service on-demand for unit/integration testing. The port is unfortunately configured by the test, so there is no guarantee that the port will be free, and the test causing the contention may not even be in the same JVM. Rather than causing tests to fail (especially in CI/CD pipelines), I'd rather that testcontainers wait and retry for the contested container resources. The container name doesn't actually matter, but the point is moot, because the port bind does matter. However, I don't want to focus too much on my particular use case, because I think a container start retry backoff strategy would be applicable more widely, such as when external resources cannot be assured, or when dealing with contention with legacy systems that don't have any sort of lock-wait mechanism, or weird rate limiting in REST APIs, etc etc.