Troubleshooting
editThe exceptions
try
{
await container.StartAsync();
}
catch (ContainerRuntimeException ex)
{
// The runtime refused an operation: a CLI command (Command, ExitCode, StandardError) or a Docker Engine API request (StatusCode)
Console.WriteLine($"{ex.Runtime} failed: {ex.Command} {ex.StatusCode} {ex.StandardError}");
throw;
}
catch (TimeoutException ex)
{
// Not ready within StartupTimeout: the message names the wait strategy, the state of the container and its last log lines
Console.WriteLine(ex.Message);
throw;
}| Exception | Thrown when |
|---|---|
| ContainerRuntimeException | The runtime refused an operation. Runtime is the runtime; Command, ExitCode, StandardOutput and StandardError describe the command line that failed; StatusCode the request the Docker Engine API refused. |
TimeoutException | The wait strategies did not complete within StartupTimeout. The message names the strategy that did not complete, the state of the container and its last log lines. |
InvalidOperationException | No runtime is available; the container exited while a log message strategy waited (the message gives its exit code and last log lines); a ReuseId designates a container created from another definition; or the container was used before StartAsync (Id, GetMappedPort, GetConnectionString). |
NotSupportedException | The runtime cannot do the operation: pausing with Apple's container, volumes with wslc, a reaper with either. |
No container runtime is available
StartAsync throws "No supported container runtime ... is available":
- Check that the runtime is installed and that its command line is on the
PATHof the test process. A test runner started by an IDE does not always have thePATHof your terminal. - Check that its daemon runs: start Docker Desktop or the Podman machine, or run
container system startfor Apple'scontainer. - When you chose a runtime driven through its command line (
docker,podman,container,wslc), the message "The '...' runtime is not available" ends with the command that checks the daemon and what it printed, or says that it timed out.wslcboots its virtual machine on demand, so the first command can fail or hang for a while after the machine was idle. - With the Docker Engine API runtime, read the end of the message: it lists the endpoints the runtime tried and why each one failed. Check
DOCKER_HOST,DOCKER_CONTEXTand the current docker context (docker context ls). See Connect to a Docker daemon.
The container is never ready
The TimeoutException says which strategy did not complete and shows the last log lines:
- The log message changed. A new version of the image may print another message: pin the image tag, and update the strategy along with it.
- The message is printed twice. Some images start the service twice during their first start; count the occurrences or add Wait.ForPort. See Wait strategies.
- The container exited. Look at the last log lines: a missing environment variable or a wrong command line usually shows there.
- The machine is slow. Pulling is not part of the timeout, but the start of a large service on a loaded build agent can be: raise StartupTimeout.
- The image does not run on the machine. An image published for x64 only, such as SQL Server, does not run on an arm64 machine unless the runtime emulates x64.
A port cannot be reached
- Use the host port:
GetMappedPort(containerPort)returns it. The container port is only reachable from the network of the container. - Connect to the address
GetHostAddress(containerPort)returns:127.0.0.1by default, the host of the daemon when it runs on another machine. See Ports. - With a daemon on another machine, publish the port on
0.0.0.0: a port published on the loopback address is only reachable from the daemon's machine. - Read the port again after StartAsync or RestartAsync.
Containers are left behind
- A test run that is killed does not dispose its containers: call CleanupAsync when the tests start, and start a reaper. See Cleaning up.
- A container that has a ReuseId is kept on purpose. See Reusing a container.
- With
wslc, the images built from a Dockerfile and the anonymous volumes are not removed.
See what the container does
- Forward its logs to a logger or to the test output. See Forward the logs to a logger.
- Inspect it with InspectAsync, or run a command in it with ExecAsync. See Working with a container.
- To look at it with the tools of the runtime,
container.Nameandcontainer.Ididentify it.