Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using System;
using JetBrains.Annotations;

namespace DotNet.Testcontainers.Configurations
{
/// <summary>
/// Represents an exception that is thrown when a Docker container fails to start.
/// </summary>
[PublicAPI]
public sealed class ContainerException : Exception
{
/// <summary>
/// Initializes a new instance of the <see cref="ContainerException" /> class.
/// </summary>
/// <param name="message">The message that describes the error.</param>
public ContainerException(string message)
: base(message)
{
}
}
}
37 changes: 37 additions & 0 deletions src/Testcontainers/Containers/DockerContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Docker.DotNet;
Expand Down Expand Up @@ -674,6 +675,9 @@
_container = await _client.Container.ByIdAsync(_container.ID, ct)
.ConfigureAwait(false);

await ThrowIfExitedAsync(ct)
.ConfigureAwait(false);

return await waitStrategy.UntilAsync(this, ct)
.ConfigureAwait(false);
}
Expand All @@ -699,6 +703,39 @@
return true;
}

private async Task ThrowIfExitedAsync(CancellationToken ct = default)
{
if (State == TestcontainersStates.Exited)
{
var message = new StringBuilder($"The {Image.FullName} container has exited.");
try
{
var (stdout, stderr) = await GetLogsAsync(ct: ct)
.ConfigureAwait(false);

stdout = stdout.Trim();
stderr = stderr.Trim();

message.AppendLine();

if (stderr.Length > 0)
{
message.AppendLine().AppendLine($"=== stderr of {Name.TrimStart('/')} ({Id}) ===").AppendLine(stderr);
}

if (stdout.Length > 0)
{
message.AppendLine().AppendLine($"=== stdout of {Name.TrimStart('/')} ({Id}) ===").AppendLine(stdout);
}
}
catch
{
message.AppendLine(" Please look at the container logs.");
}
throw new ContainerException(message.ToString());

Check failure on line 735 in src/Testcontainers/Containers/DockerContainer.cs

View workflow job for this annotation

GitHub Actions / Test Report

DotNet.Testcontainers.Tests.Unit.TestcontainersContainerTest+WithConfiguration ► BindMountAndCommand

Failed test found in: Testcontainers.Tests.trx Error: DotNet.Testcontainers.Configurations.ContainerException : The nginx:1.22 container has exited.
Raw output
DotNet.Testcontainers.Configurations.ContainerException : The nginx:1.22 container has exited.

   at DotNet.Testcontainers.Containers.DockerContainer.ThrowIfExitedAsync(CancellationToken ct) in /_/src/Testcontainers/Containers/DockerContainer.cs:line 735
   at DotNet.Testcontainers.Containers.DockerContainer.CheckReadinessAsync(WaitStrategy waitStrategy, CancellationToken ct) in /_/src/Testcontainers/Containers/DockerContainer.cs:line 678
   at DotNet.Testcontainers.Configurations.WaitStrategy.<>c__DisplayClass24_0.<<WaitUntilAsync>g__UntilAsync|0>d.MoveNext() in /_/src/Testcontainers/Configurations/WaitStrategies/WaitStrategy.cs:line 184
--- End of stack trace from previous location ---
   at DotNet.Testcontainers.Configurations.WaitStrategy.WaitUntilAsync(Func`1 wait, TimeSpan interval, TimeSpan timeout, Int32 retries, CancellationToken ct) in /_/src/Testcontainers/Configurations/WaitStrategies/WaitStrategy.cs:line 213
   at DotNet.Testcontainers.Containers.DockerContainer.CheckReadinessAsync(IEnumerable`1 waitStrategies, CancellationToken ct) in /_/src/Testcontainers/Containers/DockerContainer.cs:line 699
   at DotNet.Testcontainers.Containers.DockerContainer.UnsafeStartAsync(CancellationToken ct) in /_/src/Testcontainers/Containers/DockerContainer.cs:line 558
   at DotNet.Testcontainers.Containers.DockerContainer.StartAsync(CancellationToken ct) in /_/src/Testcontainers/Containers/DockerContainer.cs:line 341
   at DotNet.Testcontainers.Tests.Unit.TestcontainersContainerTest.WithConfiguration.BindMountAndCommand() in /home/runner/work/testcontainers-dotnet/testcontainers-dotnet/tests/Testcontainers.Tests/Unit/Containers/Unix/TestcontainersContainerTest.cs:line 251
   at DotNet.Testcontainers.Tests.Unit.TestcontainersContainerTest.WithConfiguration.BindMountAndCommand() in /home/runner/work/testcontainers-dotnet/testcontainers-dotnet/tests/Testcontainers.Tests/Unit/Containers/Unix/TestcontainersContainerTest.cs:line 257
--- End of stack trace from previous location ---

Check failure on line 735 in src/Testcontainers/Containers/DockerContainer.cs

View workflow job for this annotation

GitHub Actions / Test Report

DotNet.Testcontainers.Tests.Unit.TestcontainersContainerTest+WithConfiguration ► BindMountAndEnvironment

Failed test found in: Testcontainers.Tests.trx Error: DotNet.Testcontainers.Configurations.ContainerException : The nginx:1.22 container has exited.
Raw output
DotNet.Testcontainers.Configurations.ContainerException : The nginx:1.22 container has exited.

   at DotNet.Testcontainers.Containers.DockerContainer.ThrowIfExitedAsync(CancellationToken ct) in /_/src/Testcontainers/Containers/DockerContainer.cs:line 735
   at DotNet.Testcontainers.Containers.DockerContainer.CheckReadinessAsync(WaitStrategy waitStrategy, CancellationToken ct) in /_/src/Testcontainers/Containers/DockerContainer.cs:line 678
   at DotNet.Testcontainers.Configurations.WaitStrategy.<>c__DisplayClass24_0.<<WaitUntilAsync>g__UntilAsync|0>d.MoveNext() in /_/src/Testcontainers/Configurations/WaitStrategies/WaitStrategy.cs:line 184
--- End of stack trace from previous location ---
   at DotNet.Testcontainers.Configurations.WaitStrategy.WaitUntilAsync(Func`1 wait, TimeSpan interval, TimeSpan timeout, Int32 retries, CancellationToken ct) in /_/src/Testcontainers/Configurations/WaitStrategies/WaitStrategy.cs:line 213
   at DotNet.Testcontainers.Containers.DockerContainer.CheckReadinessAsync(IEnumerable`1 waitStrategies, CancellationToken ct) in /_/src/Testcontainers/Containers/DockerContainer.cs:line 699
   at DotNet.Testcontainers.Containers.DockerContainer.UnsafeStartAsync(CancellationToken ct) in /_/src/Testcontainers/Containers/DockerContainer.cs:line 548
   at DotNet.Testcontainers.Containers.DockerContainer.StartAsync(CancellationToken ct) in /_/src/Testcontainers/Containers/DockerContainer.cs:line 341
   at DotNet.Testcontainers.Tests.Unit.TestcontainersContainerTest.WithConfiguration.BindMountAndEnvironment() in /home/runner/work/testcontainers-dotnet/testcontainers-dotnet/tests/Testcontainers.Tests/Unit/Containers/Unix/TestcontainersContainerTest.cs:line 280
   at DotNet.Testcontainers.Tests.Unit.TestcontainersContainerTest.WithConfiguration.BindMountAndEnvironment() in /home/runner/work/testcontainers-dotnet/testcontainers-dotnet/tests/Testcontainers.Tests/Unit/Containers/Unix/TestcontainersContainerTest.cs:line 286
--- End of stack trace from previous location ---

Check failure on line 735 in src/Testcontainers/Containers/DockerContainer.cs

View workflow job for this annotation

GitHub Actions / Test Report

DotNet.Testcontainers.Tests.Unit.TestcontainersContainerTest+WithConfiguration ► Entrypoint

Failed test found in: Testcontainers.Tests.trx Error: DotNet.Testcontainers.Configurations.ContainerException : The alpine:3.17 container has exited.
Raw output
DotNet.Testcontainers.Configurations.ContainerException : The alpine:3.17 container has exited.

   at DotNet.Testcontainers.Containers.DockerContainer.ThrowIfExitedAsync(CancellationToken ct) in /_/src/Testcontainers/Containers/DockerContainer.cs:line 735
   at DotNet.Testcontainers.Containers.DockerContainer.CheckReadinessAsync(WaitStrategy waitStrategy, CancellationToken ct) in /_/src/Testcontainers/Containers/DockerContainer.cs:line 678
   at DotNet.Testcontainers.Configurations.WaitStrategy.<>c__DisplayClass24_0.<<WaitUntilAsync>g__UntilAsync|0>d.MoveNext() in /_/src/Testcontainers/Configurations/WaitStrategies/WaitStrategy.cs:line 184
--- End of stack trace from previous location ---
   at DotNet.Testcontainers.Configurations.WaitStrategy.WaitUntilAsync(Func`1 wait, TimeSpan interval, TimeSpan timeout, Int32 retries, CancellationToken ct) in /_/src/Testcontainers/Configurations/WaitStrategies/WaitStrategy.cs:line 213
   at DotNet.Testcontainers.Containers.DockerContainer.CheckReadinessAsync(IEnumerable`1 waitStrategies, CancellationToken ct) in /_/src/Testcontainers/Containers/DockerContainer.cs:line 699
   at DotNet.Testcontainers.Containers.DockerContainer.UnsafeStartAsync(CancellationToken ct) in /_/src/Testcontainers/Containers/DockerContainer.cs:line 548
   at DotNet.Testcontainers.Containers.DockerContainer.StartAsync(CancellationToken ct) in /_/src/Testcontainers/Containers/DockerContainer.cs:line 341
   at DotNet.Testcontainers.Tests.Unit.TestcontainersContainerTest.WithConfiguration.Entrypoint() in /home/runner/work/testcontainers-dotnet/testcontainers-dotnet/tests/Testcontainers.Tests/Unit/Containers/Unix/TestcontainersContainerTest.cs:line 138
   at DotNet.Testcontainers.Tests.Unit.TestcontainersContainerTest.WithConfiguration.Entrypoint() in /home/runner/work/testcontainers-dotnet/testcontainers-dotnet/tests/Testcontainers.Tests/Unit/Containers/Unix/TestcontainersContainerTest.cs:line 145
--- End of stack trace from previous location ---

Check failure on line 735 in src/Testcontainers/Containers/DockerContainer.cs

View workflow job for this annotation

GitHub Actions / Test Report

DotNet.Testcontainers.Tests.Unit.TestcontainersContainerTest+WithConfiguration ► Hostname

Failed test found in: Testcontainers.Tests.trx Error: DotNet.Testcontainers.Configurations.ContainerException : The alpine:3.17 container has exited.
Raw output
DotNet.Testcontainers.Configurations.ContainerException : The alpine:3.17 container has exited.

   at DotNet.Testcontainers.Containers.DockerContainer.ThrowIfExitedAsync(CancellationToken ct) in /_/src/Testcontainers/Containers/DockerContainer.cs:line 735
   at DotNet.Testcontainers.Containers.DockerContainer.CheckReadinessAsync(WaitStrategy waitStrategy, CancellationToken ct) in /_/src/Testcontainers/Containers/DockerContainer.cs:line 678
   at DotNet.Testcontainers.Configurations.WaitStrategy.<>c__DisplayClass24_0.<<WaitUntilAsync>g__UntilAsync|0>d.MoveNext() in /_/src/Testcontainers/Configurations/WaitStrategies/WaitStrategy.cs:line 184
--- End of stack trace from previous location ---
   at DotNet.Testcontainers.Configurations.WaitStrategy.WaitUntilAsync(Func`1 wait, TimeSpan interval, TimeSpan timeout, Int32 retries, CancellationToken ct) in /_/src/Testcontainers/Configurations/WaitStrategies/WaitStrategy.cs:line 213
   at DotNet.Testcontainers.Containers.DockerContainer.CheckReadinessAsync(IEnumerable`1 waitStrategies, CancellationToken ct) in /_/src/Testcontainers/Containers/DockerContainer.cs:line 699
   at DotNet.Testcontainers.Containers.DockerContainer.UnsafeStartAsync(CancellationToken ct) in /_/src/Testcontainers/Containers/DockerContainer.cs:line 548
   at DotNet.Testcontainers.Containers.DockerContainer.StartAsync(CancellationToken ct) in /_/src/Testcontainers/Containers/DockerContainer.cs:line 341
   at DotNet.Testcontainers.Tests.Unit.TestcontainersContainerTest.WithConfiguration.Hostname() in /home/runner/work/testcontainers-dotnet/testcontainers-dotnet/tests/Testcontainers.Tests/Unit/Containers/Unix/TestcontainersContainerTest.cs:line 77
   at DotNet.Testcontainers.Tests.Unit.TestcontainersContainerTest.WithConfiguration.Hostname() in /home/runner/work/testcontainers-dotnet/testcontainers-dotnet/tests/Testcontainers.Tests/Unit/Containers/Unix/TestcontainersContainerTest.cs:line 84
--- End of stack trace from previous location ---

Check failure on line 735 in src/Testcontainers/Containers/DockerContainer.cs

View workflow job for this annotation

GitHub Actions / Test Report

DotNet.Testcontainers.Tests.Unit.TestcontainersContainerTest+WithConfiguration ► OutputConsumer

Failed test found in: Testcontainers.Tests.trx Error: DotNet.Testcontainers.Configurations.ContainerException : The alpine:3.17 container has exited. === stderr of peaceful_heisenberg (3746ad39ee3d8ba3979567aafc6c60e412e3b26496fc5d25bad6e4de6f072594) === 2025-10-01T18:00:54.331429836Z 1759341654167 === stdout of peaceful_heisenberg (3746ad39ee3d8ba3979567aafc6c60e412e3b26496fc5d25bad6e4de6f072594) === 2025-10-01T18:00:54.331424032Z 1759341654167
Raw output
DotNet.Testcontainers.Configurations.ContainerException : The alpine:3.17 container has exited.

=== stderr of peaceful_heisenberg (3746ad39ee3d8ba3979567aafc6c60e412e3b26496fc5d25bad6e4de6f072594) ===
2025-10-01T18:00:54.331429836Z 1759341654167

=== stdout of peaceful_heisenberg (3746ad39ee3d8ba3979567aafc6c60e412e3b26496fc5d25bad6e4de6f072594) ===
2025-10-01T18:00:54.331424032Z 1759341654167

   at DotNet.Testcontainers.Containers.DockerContainer.ThrowIfExitedAsync(CancellationToken ct) in /_/src/Testcontainers/Containers/DockerContainer.cs:line 735
   at DotNet.Testcontainers.Containers.DockerContainer.CheckReadinessAsync(WaitStrategy waitStrategy, CancellationToken ct) in /_/src/Testcontainers/Containers/DockerContainer.cs:line 678
   at DotNet.Testcontainers.Configurations.WaitStrategy.<>c__DisplayClass24_0.<<WaitUntilAsync>g__UntilAsync|0>d.MoveNext() in /_/src/Testcontainers/Configurations/WaitStrategies/WaitStrategy.cs:line 184
--- End of stack trace from previous location ---
   at DotNet.Testcontainers.Configurations.WaitStrategy.WaitUntilAsync(Func`1 wait, TimeSpan interval, TimeSpan timeout, Int32 retries, CancellationToken ct) in /_/src/Testcontainers/Configurations/WaitStrategies/WaitStrategy.cs:line 213
   at DotNet.Testcontainers.Containers.DockerContainer.CheckReadinessAsync(IEnumerable`1 waitStrategies, CancellationToken ct) in /_/src/Testcontainers/Containers/DockerContainer.cs:line 699
   at DotNet.Testcontainers.Containers.DockerContainer.UnsafeStartAsync(CancellationToken ct) in /_/src/Testcontainers/Containers/DockerContainer.cs:line 548
   at DotNet.Testcontainers.Containers.DockerContainer.StartAsync(CancellationToken ct) in /_/src/Testcontainers/Containers/DockerContainer.cs:line 341
   at DotNet.Testcontainers.Tests.Unit.TestcontainersContainerTest.WithConfiguration.OutputConsumer() in /home/runner/work/testcontainers-dotnet/testcontainers-dotnet/tests/Testcontainers.Tests/Unit/Containers/Unix/TestcontainersContainerTest.cs:line 343
   at DotNet.Testcontainers.Tests.Unit.TestcontainersContainerTest.WithConfiguration.OutputConsumer() in /home/runner/work/testcontainers-dotnet/testcontainers-dotnet/tests/Testcontainers.Tests/Unit/Containers/Unix/TestcontainersContainerTest.cs:line 359
--- End of stack trace from previous location ---

Check failure on line 735 in src/Testcontainers/Containers/DockerContainer.cs

View workflow job for this annotation

GitHub Actions / Test Report

DotNet.Testcontainers.Tests.Unit.TestcontainersContainerTest+WithConfiguration ► WorkingDirectory

Failed test found in: Testcontainers.Tests.trx Error: DotNet.Testcontainers.Configurations.ContainerException : The alpine:3.17 container has exited.
Raw output
DotNet.Testcontainers.Configurations.ContainerException : The alpine:3.17 container has exited.

   at DotNet.Testcontainers.Containers.DockerContainer.ThrowIfExitedAsync(CancellationToken ct) in /_/src/Testcontainers/Containers/DockerContainer.cs:line 735
   at DotNet.Testcontainers.Containers.DockerContainer.CheckReadinessAsync(WaitStrategy waitStrategy, CancellationToken ct) in /_/src/Testcontainers/Containers/DockerContainer.cs:line 678
   at DotNet.Testcontainers.Configurations.WaitStrategy.<>c__DisplayClass24_0.<<WaitUntilAsync>g__UntilAsync|0>d.MoveNext() in /_/src/Testcontainers/Configurations/WaitStrategies/WaitStrategy.cs:line 184
--- End of stack trace from previous location ---
   at DotNet.Testcontainers.Configurations.WaitStrategy.WaitUntilAsync(Func`1 wait, TimeSpan interval, TimeSpan timeout, Int32 retries, CancellationToken ct) in /_/src/Testcontainers/Configurations/WaitStrategies/WaitStrategy.cs:line 213
   at DotNet.Testcontainers.Containers.DockerContainer.CheckReadinessAsync(IEnumerable`1 waitStrategies, CancellationToken ct) in /_/src/Testcontainers/Containers/DockerContainer.cs:line 699
   at DotNet.Testcontainers.Containers.DockerContainer.UnsafeStartAsync(CancellationToken ct) in /_/src/Testcontainers/Containers/DockerContainer.cs:line 548
   at DotNet.Testcontainers.Containers.DockerContainer.StartAsync(CancellationToken ct) in /_/src/Testcontainers/Containers/DockerContainer.cs:line 341
   at DotNet.Testcontainers.Tests.Unit.TestcontainersContainerTest.WithConfiguration.WorkingDirectory() in /home/runner/work/testcontainers-dotnet/testcontainers-dotnet/tests/Testcontainers.Tests/Unit/Containers/Unix/TestcontainersContainerTest.cs:line 118
   at DotNet.Testcontainers.Tests.Unit.TestcontainersContainerTest.WithConfiguration.WorkingDirectory() in /home/runner/work/testcontainers-dotnet/testcontainers-dotnet/tests/Testcontainers.Tests/Unit/Containers/Unix/TestcontainersContainerTest.cs:line 125
--- End of stack trace from previous location ---
}
}

private sealed class WaitUntilPortBindingsMapped : WaitStrategy
{
private readonly DockerContainer _parent;
Expand Down
3 changes: 3 additions & 0 deletions tests/Testcontainers.Platform.Linux.Tests/DependsOnTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ public async ValueTask InitializeAsync()
{
var childContainer1 = new ContainerBuilder()
.WithImage(CommonImages.Alpine)
.WithEntrypoint(CommonCommands.SleepInfinity)
.WithLabel(_labelKey, _labelValue)
.Build();

var childContainer2 = new ContainerBuilder()
.WithImage(CommonImages.Alpine)
.WithEntrypoint(CommonCommands.SleepInfinity)
.WithLabel(_labelKey, _labelValue)
.Build();

Expand All @@ -41,6 +43,7 @@ public async ValueTask InitializeAsync()
.DependsOn(network)
.DependsOn(volume, "/workdir")
.WithImage(CommonImages.Alpine)
.WithEntrypoint(CommonCommands.SleepInfinity)
.WithLabel(_labelKey, _labelValue)
.Build();

Expand Down
10 changes: 0 additions & 10 deletions tests/Testcontainers.Platform.Linux.Tests/PortForwardingTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ public PortForwardingDefaultConfiguration(HostedService fixture)
.WithAutoRemove(false)
.WithEntrypoint("nc")
.WithCommand(HostedService.Host, fixture.Port.ToString(CultureInfo.InvariantCulture))
.WithWaitStrategy(Wait.ForUnixContainer().AddCustomWaitStrategy(new WaitUntil()))
.Build())
{
}
Expand All @@ -67,7 +66,6 @@ public PortForwardingNetworkConfiguration(HostedService fixture)
.WithEntrypoint("nc")
.WithCommand(HostedService.Host, fixture.Port.ToString(CultureInfo.InvariantCulture))
.WithNetwork(new NetworkBuilder().Build())
.WithWaitStrategy(Wait.ForUnixContainer().AddCustomWaitStrategy(new WaitUntil()))
.Build())
{
}
Expand Down Expand Up @@ -115,12 +113,4 @@ private async Task AcceptSocketAsync()
.ConfigureAwait(false);
}
}

private sealed class WaitUntil : IWaitUntil
{
public Task<bool> UntilAsync(IContainer container)
{
return Task.FromResult(TestcontainersStates.Exited.Equals(container.State));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@ public async Task DockerEndpoint()
await using var container = new ContainerBuilder()
.WithDockerEndpoint(TestcontainersSettings.OS.DockerEndpointAuthConfig)
.WithImage(CommonImages.Alpine)
.WithEntrypoint(CommonCommands.SleepInfinity)
.Build();

// When
Expand Down
Loading