Problem
Testcontainers for .NET currently performs a single image pull attempt. A transient registry or network failure therefore aborts the container startup and the entire test session, even when an immediate retry would succeed.
We observed this in a GitHub Actions job using Testcontainers 4.7.0, Docker on ubuntu-latest, and redis:7-alpine:
Docker API responded with status code=InternalServerError,
response={"message":"Head \"https://registry-1.docker.io/v2/library/redis/manifests/7-alpine\": ... read: connection reset by peer"}
Failed run: https://github.com/thomhurst/Respire/actions/runs/31280152764/attempts/1
Re-running only the failed job passed without any source change. Because container initialization was shared for the test session, this single transient pull failure caused all five authentication tests to fail before execution.
Current develop appears to call the image creation operation once without a retry:
Solution
Add a bounded retry policy around image pulls for clearly transient failures, while honoring the supplied cancellation token.
A possible default policy:
- retry a small number of times, such as three attempts;
- use exponential backoff with jitter;
- retry transport failures, timeouts, HTTP 408/429, and Docker API 5xx responses;
- honor
Retry-After where available;
- do not retry permanent failures such as invalid image names, authentication/authorization failures, or missing manifests;
- log each retry with the image name, attempt, delay, and sanitized failure reason.
Making the policy configurable would be useful, but a conservative built-in default would address the common CI failure mode.
Benefit
This would reduce flaky integration-test failures caused by short-lived Docker Hub, registry-auth, proxy, DNS, or network interruptions. It also keeps retry behavior consistent across CI systems instead of requiring every Testcontainers consumer to wrap container startup or pre-pull images independently.
Alternatives
- Pre-pull images in CI with a shell-level retry loop.
- Cache required images on self-hosted runners.
- Wrap
StartAsync in application code, although this retries more than the image pull and can repeat container/resource setup.
- Leave retries entirely to Docker Engine; in this case Docker returned the transient registry error immediately, so no effective retry occurred.
Would you like to help contributing this enhancement?
Yes
Problem
Testcontainers for .NET currently performs a single image pull attempt. A transient registry or network failure therefore aborts the container startup and the entire test session, even when an immediate retry would succeed.
We observed this in a GitHub Actions job using Testcontainers 4.7.0, Docker on
ubuntu-latest, andredis:7-alpine:Failed run: https://github.com/thomhurst/Respire/actions/runs/31280152764/attempts/1
Re-running only the failed job passed without any source change. Because container initialization was shared for the test session, this single transient pull failure caused all five authentication tests to fail before execution.
Current
developappears to call the image creation operation once without a retry:TestcontainersClient.PullImageAsyncDockerImageOperations.CreateAsyncSolution
Add a bounded retry policy around image pulls for clearly transient failures, while honoring the supplied cancellation token.
A possible default policy:
Retry-Afterwhere available;Making the policy configurable would be useful, but a conservative built-in default would address the common CI failure mode.
Benefit
This would reduce flaky integration-test failures caused by short-lived Docker Hub, registry-auth, proxy, DNS, or network interruptions. It also keeps retry behavior consistent across CI systems instead of requiring every Testcontainers consumer to wrap container startup or pre-pull images independently.
Alternatives
StartAsyncin application code, although this retries more than the image pull and can repeat container/resource setup.Would you like to help contributing this enhancement?
Yes