ResourceReaperException: Initialization has been cancelled
Describe the bug In some cases Testcontainers can't connect to Ryuk. You'll see the following log message:
ResourceReaperException: Initialization has been cancelled.
Docker Desktop for Windows assigns a random public host port from the excluded port range. The container starts, but the service behind the public host port is not available.
To Reproduce
- https://github.com/dotnet/Docker.DotNet/issues/565
- https://github.com/docker/for-win/issues/11584
Expected behavior Testcontainers can connect to Ryuk.
Screenshots -
Desktop (please complete the following information):
- Docker Desktop for Windows 4.9.0 (80466)
Additional context
- https://github.com/docker/for-win/issues/3171
- https://github.com/docker/for-win/issues/11584
- #449, #443
Workaround
Disable the ResourceReaper (TestcontainersSettings.ResourceReaperEnabled = false) or use the TestcontainersSettings.ResourceReaperPublicHostPort function to return an available port.
Note: this issue may affect any container with a random host port binding, not only Ryuk. So you may have issues like "cannot connect to DB"
But for "regular" containers it is possible do define port binding manually to workaround the issue.
Note: this issue may affect any container with a random host port binding, not only Ryuk.
That concerns me too, but at least most of the pipelines don't use the Windows version, I guess. Have you tried the workarounds where they suggest restarting some Windows services?
Yes, I never had problems with CI pipelines. Usually the problem is for local test executions.
Restarting the winnat service works, yes. But personally, I will systematically use something similar to .WithPortBinding(GetNextTcpPort(), myDbPort) to avoid bad surprises. Especially for other developers in the team, who may not always be aware of this issue.
Also seeing this on MacOS (I'm on 12.5.1 right now).
If I can provide useful info that you don't already have, please let me know.
How frequently do you get the exception? Which Docker version do you use? Can you share the exception and your test configuration?
@HofmeisterAn , I stumbled over your library and want to give it a try. Unfortunately, I'm suffering from this issue as well 😕 could you please give an example of how I can apply the mentioned workaround (TestcontainersSettings.ResourceReaperPublicHostPort)? This is my current code:
_postgresContainer = new ContainerBuilder()
.WithImage("postgres:latest")
.WithNetwork(_network)
.WithNetworkAliases("postgresql")
.WithPortBinding(TestcontainersSettings.ResourceReaperPublicHostPort.Invoke(<<what comes here?>>), 7777)
.WithPortBinding(5432, 5432)
.WithEnvironment("POSTGRES_USER", "theAdmin")
.WithEnvironment("POSTGRES_DB", "theDatabase")
.WithEnvironment("POSTGRES_PASSWORD", "thePassword")
.WithWaitStrategy(Wait.ForUnixContainer().UntilPortIsAvailable(5432))
.WithCleanUp(true)
.Build();
Thanks in advance!
@mu88 can you please test develop and see if you still have the issue? To answer your question, you need to set the ResourceReaperPublicHostPort callback before creating any resource, like:
public sealed class GitHub
{
static GitHub()
{
TestcontainersSettings.ResourceReaperPublicHostPort = _ =>
{
using (var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
socket.Bind(new IPEndPoint(IPAddress.Loopback, 0));
return (ushort)((IPEndPoint)socket.LocalEndPoint).Port;
}
};
}
[Fact]
public async Task Test()
{
await new ContainerBuilder()
.WithImage(CommonImages.Alpine)
.WithEntrypoint(CommonCommands.SleepInfinity)
.WithPortBinding(80, true)
.Build()
.StartAsync();
}
}
Please note, your configuration does not follow the best practices. PostgreSQL requires a different wait strategy too, waiting until the port is available is usually not enough. This is our module configuration. The module will be part the the release this week.
Thx for your super-quick reply! I'll give the TestcontainersSettings.ResourceReaperPublicHostPort config a try 💪🏻
Regarding your question:
can you please test
developand see if you still have the issue?
I can give it a try, sure 🙃 How can I do so? Do you have a prerelease NuGet package that I can consume? Or do I have to clone your repo and build a NuGet package on my own?
And regarding the best practices, what specifically do you mean? The .WithPortBinding() call? I'm trying to "translate" a docker-compose.yml consisting of four containers:
- ZooKeeper
- PostgreSQL
- Kafka1 (depends on ZooKeeper)
- Kafka2 (depends on ZooKeeper)
So Kafka needs to know the ZooKeeper port. How can I assign a random port of zooKeeperContainer to kafkaContainer before actually running the containers?
Furthermore, is there any smart pattern that I can adopt to express the dependencies between containers? For example, in docker-compose.yaml I can write depends_on and Docker automatically knows the order in which the containers need to be started. In my code, I've to manually take the order into account.
Or do I have to clone your repo and build a NuGet package on my own?
Yes, you would need to clone the repository. You do not need to build your own NuGet package, you can simply add it as a reference to your test project.
The
.WithPortBinding()call?
Yes, it is better to use random assigned host port. For container-to-container communication you simply connect via network-alias:container-port, here is an example.
How can I assign a random port of
zooKeeperContainertokafkaContainerbefore actually running the containers?
Yes, configuring Kafka can be a bit difficult. Here is the configuration for our Kafka module, which currently does not support an external Zookeeper. However, I know that Java supports it, so perhaps you would like to take a look at how Java does it. Of course, it would be great if you could contribute back. Having external Zookeeper support out of the box would be fantastic.
Furthermore, is there any smart pattern that I can adopt to express the dependencies between containers?
Not yet, but it's something we will add in the release following this one. The Web Driver module has similar dependencies. Currently, we keep the dependent Docker resources in the configuration instance. But we will have a proper API for that in the future.
All of the topics are off-topic, though. If you require further assistance or encounter any difficulties with the Testcontainers API, please do not hesitate to contact us on Slack.
I can confirm that it is working with today's develop branch 👍🏻 thank you for your help!
@HofmeisterAn , waiting forward for the release that fixes this issue
Since we now have the new release, I will close this issue. Let's see if it reappears 🤞.
I can confirm that it works with v.3.0 - thank you for your great work!