Skip to content

Conversation

@HofmeisterAn
Copy link
Collaborator

@HofmeisterAn HofmeisterAn commented Dec 20, 2025

What does this PR do?

This PR updates Docker.DotNet to a version compatible with Docker Engine v29. There is one caveat: Docker.DotNet does not properly support downgrading (pinning) the Docker Engine API. While version pinning is technically supported, the library does not include the required request/response types and APIs for older versions.

Each Docker.DotNet release is effectively compatible with a single Docker Engine API version, and the library does not support multiple versions at the same time. The updated version officially supports API version 1.52.

This has been a known issue for many years but fortunately hasn't caused major problems. In practice, the library has appeared "compatible" with different Docker Engine API versions because only a limited set of APIs is used.

In the future, I plan to change the underlying Docker.DotNet implementation to support multiple API versions, routing requests and responses to the correct types based on the selected endpoint version.

I ran extensive tests and didn't encounter any major issues. There were a few incompatibilities, but I was able to work around them in Testcontainers.

Why is it important?

-

Related issues

-

Summary by CodeRabbit

  • New Features

    • Added support for nullable exit codes in container execution results.
  • Bug Fixes

    • Improved network and MAC address configuration handling for containers.
    • Enhanced logging for Docker operations.
  • Chores

    • Updated .NET version to 10.0 in development container.
    • Updated Windows Server image to ltsc2025.
    • Bumped package dependencies.
    • Increased test timeout and default connection timeout.

✏️ Tip: You can customize this high-level summary in your review settings.

@HofmeisterAn HofmeisterAn added the enhancement New feature or request label Dec 20, 2025
@netlify
Copy link

netlify bot commented Dec 20, 2025

Deploy Preview for testcontainers-dotnet ready!

Name Link
🔨 Latest commit f49e6d8
🔍 Latest deploy log https://app.netlify.com/projects/testcontainers-dotnet/deploys/6946c1bb08a7db0008cf9041
😎 Deploy Preview https://deploy-preview-1609--testcontainers-dotnet.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link

coderabbitai bot commented Dec 20, 2025

Walkthrough

This PR applies multiple maintenance and configuration updates across the development environment, CI/CD pipelines, and source code. Updates include .NET feature version, action versions, NuGet package versions, timeout configurations, network handling logic, null-safety type changes, and Windows image references.

Changes

Cohort / File(s) Summary
Infrastructure & Configuration
.devcontainer/devcontainer.json
Updated .NET devcontainer feature from version 9.0 to 10.0 with dotnet:2.4.1
CI/CD Workflow Updates
.github/workflows/test-report.yml
Upgraded test-reporter action from v2.1.1 to v2.3.0
Build Configuration
build/Tasks.cs
Increased DotNetTest blame-hang timeout from 5 to 10 minutes
Package Dependencies
Directory.Packages.props
Bumped Docker.DotNet.Enhanced and Docker.DotNet.Enhanced.X509 from 3.130.0 to 3.131.1
Container Networking
src/Testcontainers/Clients/ContainerConfigurationConverter.cs
Modified network conversion to reuse single EndpointSettings instance with both Aliases and MacAddress across all networks
Container Operations
src/Testcontainers/Clients/DockerContainerOperations.cs
Removed MacAddress assignment from CreateContainerParameters in RunAsync
Progress Logging
src/Testcontainers/Clients/TraceProgress.cs
Enhanced logging with early error handling, debug gating, stream handling, and improved progress/status/auxiliary data formatting
Connection Timeout
src/Testcontainers/Configurations/AuthConfigs/DockerEndpointAuthenticationConfiguration.cs
Increased NamedPipeConnectionTimeout default from 1 second to 5 seconds
Exec Result Type Safety
src/Testcontainers/Containers/ExecResult.cs
Changed ExitCode property and constructor parameter from long to long? (nullable)
Test Image References
tests/Testcontainers.Commons/CommonImages.cs
Updated ServerCore image from ltsc2022 to ltsc2025
Test Runner Configuration
tests/Testcontainers.Platform.Windows.Tests/.runs-on
Updated Windows runner image from windows-2022 to windows-2025
Unit Test Enhancement
tests/Testcontainers.Tests/Unit/Containers/Unix/TestcontainersContainerTest.cs
Added network creation and attachment in MacAddress test via NetworkBuilder

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Areas requiring attention:

  • Network/MAC address refactoring: Verify that moving MacAddress assignment from DockerContainerOperations to ContainerConfigurationConverter doesn't alter intended Docker API behavior
  • Null-safety change in ExecResult: Confirm all callers properly handle long? exit code and that null values represent a valid state
  • Progress logging enhancements: Review the new logging format, early returns, and edge cases (e.g., simultaneous Error and Progress conditions)
  • Connection timeout increase: Validate that 5-second NamedPipeConnectionTimeout is appropriate for all use cases

Possibly related PRs

Poem

🐰 A rabbit hops through versions old and new,
Ten-dot-oh, windows twenty-five—a zoo!
Networks aligned, timeouts expanded wide,
Null-safety tucked, no exit code can hide,
Enhancement and polish, all in stride! 🎉

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change - adding Docker Engine v29 support - which aligns with the PR's primary objective of updating Docker.DotNet compatibility.
Description check ✅ Passed The description includes the mandatory 'What does this PR do?' and 'Why is it important?' sections, with detailed explanation of changes, caveats, and technical context. However, 'Why is it important?' is marked with '\-' (incomplete) rather than containing substantive content.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/test-docker-engine-v29

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/Testcontainers/Clients/TraceProgress.cs (1)

49-52: Consider wrapping JsonSerializer in try-catch for robustness.

While unlikely, JsonSerializer.Serialize could throw if ExtensionData contains problematic types (e.g., circular references). Consider adding exception handling to prevent logging failures from impacting Docker operations.

🔎 Optional: Add defensive exception handling
 if (value.Aux != null)
 {
-  _logger.LogDebug("Auxiliary data: {ExtensionData}", JsonSerializer.Serialize(value.Aux.ExtensionData));
+  try
+  {
+    _logger.LogDebug("Auxiliary data: {ExtensionData}", JsonSerializer.Serialize(value.Aux.ExtensionData));
+  }
+  catch (Exception ex)
+  {
+    _logger.LogWarning(ex, "Failed to serialize auxiliary data");
+  }
 }
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8a7b97e and f49e6d8.

📒 Files selected for processing (12)
  • .devcontainer/devcontainer.json (1 hunks)
  • .github/workflows/test-report.yml (1 hunks)
  • Directory.Packages.props (1 hunks)
  • build/Tasks.cs (1 hunks)
  • src/Testcontainers/Clients/ContainerConfigurationConverter.cs (1 hunks)
  • src/Testcontainers/Clients/DockerContainerOperations.cs (0 hunks)
  • src/Testcontainers/Clients/TraceProgress.cs (2 hunks)
  • src/Testcontainers/Configurations/AuthConfigs/DockerEndpointAuthenticationConfiguration.cs (1 hunks)
  • src/Testcontainers/Containers/ExecResult.cs (2 hunks)
  • tests/Testcontainers.Commons/CommonImages.cs (1 hunks)
  • tests/Testcontainers.Platform.Windows.Tests/.runs-on (1 hunks)
  • tests/Testcontainers.Tests/Unit/Containers/Unix/TestcontainersContainerTest.cs (1 hunks)
💤 Files with no reviewable changes (1)
  • src/Testcontainers/Clients/DockerContainerOperations.cs
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: diegosasw
Repo: testcontainers/testcontainers-dotnet PR: 1583
File: src/Testcontainers.KurrentDb/Testcontainers.KurrentDb.csproj:7-7
Timestamp: 2025-11-17T17:58:43.958Z
Learning: In the testcontainers-dotnet repository, JetBrains.Annotations should use version 2023.3.0 to maintain consistency with the main Testcontainers csproj, rather than always using the latest available version.
📚 Learning: 2025-11-23T18:56:42.711Z
Learnt from: verdie-g
Repo: testcontainers/testcontainers-dotnet PR: 1585
File: src/Testcontainers.Milvus/MilvusBuilder.cs:77-87
Timestamp: 2025-11-23T18:56:42.711Z
Learning: In testcontainers-dotnet, the HealthcheckConfig.StartPeriod property (from Docker.DotNet) is of type long and represents duration in nanoseconds, not TimeSpan. For example, 90 seconds should be represented as 90 * 1_000_000_000L.

Applied to files:

  • src/Testcontainers/Configurations/AuthConfigs/DockerEndpointAuthenticationConfiguration.cs
📚 Learning: 2025-11-17T17:58:43.958Z
Learnt from: diegosasw
Repo: testcontainers/testcontainers-dotnet PR: 1583
File: src/Testcontainers.KurrentDb/Testcontainers.KurrentDb.csproj:7-7
Timestamp: 2025-11-17T17:58:43.958Z
Learning: In the testcontainers-dotnet repository, JetBrains.Annotations should use version 2023.3.0 to maintain consistency with the main Testcontainers csproj, rather than always using the latest available version.

Applied to files:

  • Directory.Packages.props
  • tests/Testcontainers.Platform.Windows.Tests/.runs-on
  • tests/Testcontainers.Commons/CommonImages.cs
  • src/Testcontainers/Clients/TraceProgress.cs
  • .devcontainer/devcontainer.json
🧬 Code graph analysis (2)
src/Testcontainers/Configurations/AuthConfigs/DockerEndpointAuthenticationConfiguration.cs (4)
src/Testcontainers/Builders/TestcontainersEndpointAuthenticationProvider.cs (3)
  • TimeSpan (151-154)
  • TimeSpan (157-160)
  • TimeSpan (163-166)
src/Testcontainers/Configurations/CustomConfiguration.cs (3)
  • TimeSpan (121-124)
  • TimeSpan (126-129)
  • TimeSpan (131-134)
src/Testcontainers/Configurations/EnvironmentConfiguration.cs (6)
  • TimeSpan (179-182)
  • TimeSpan (185-188)
  • TimeSpan (191-194)
  • EnvironmentConfiguration (11-195)
  • EnvironmentConfiguration (49-51)
  • EnvironmentConfiguration (56-80)
src/Testcontainers/Configurations/PropertiesFileConfiguration.cs (8)
  • TimeSpan (165-169)
  • TimeSpan (172-176)
  • TimeSpan (179-183)
  • PropertiesFileConfiguration (12-184)
  • PropertiesFileConfiguration (14-16)
  • PropertiesFileConfiguration (21-24)
  • PropertiesFileConfiguration (30-35)
  • PropertiesFileConfiguration (41-51)
tests/Testcontainers.Commons/CommonImages.cs (1)
src/Testcontainers/Images/DockerImage.cs (4)
  • DockerImage (38-41)
  • DockerImage (48-51)
  • DockerImage (62-75)
  • DockerImage (77-112)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (65)
  • GitHub Check: ci (Testcontainers.Cassandra, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.Azurite, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.ActiveMq, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.Bigtable, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.ArangoDb, ubuntu-24.04)
  • GitHub Check: analyze (csharp)
  • GitHub Check: ci (Testcontainers.Cassandra, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.Azurite, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.ActiveMq, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.Bigtable, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.ArangoDb, ubuntu-24.04)
  • GitHub Check: analyze (csharp)
  • GitHub Check: ci (Testcontainers.Cassandra, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.Azurite, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.ActiveMq, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.ClickHouse, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.Bigtable, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.ArangoDb, ubuntu-24.04)
  • GitHub Check: analyze (csharp)
  • GitHub Check: ci (Testcontainers.Cassandra, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.Azurite, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.ActiveMq, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.ClickHouse, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.Bigtable, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.ArangoDb, ubuntu-24.04)
  • GitHub Check: analyze (csharp)
  • GitHub Check: ci (Testcontainers.Cassandra, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.Azurite, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.ActiveMq, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.ClickHouse, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.Bigtable, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.ArangoDb, ubuntu-24.04)
  • GitHub Check: analyze (csharp)
  • GitHub Check: ci (Testcontainers.Cassandra, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.Azurite, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.ClickHouse, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.Bigtable, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.ArangoDb, ubuntu-24.04)
  • GitHub Check: analyze (csharp)
  • GitHub Check: ci (Testcontainers.Cassandra, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.Azurite, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.ClickHouse, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.Bigtable, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.ArangoDb, ubuntu-24.04)
  • GitHub Check: analyze (csharp)
  • GitHub Check: ci (Testcontainers.Cassandra, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.Azurite, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.CockroachDb, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.ClickHouse, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.Bigtable, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.ArangoDb, ubuntu-24.04)
  • GitHub Check: analyze (csharp)
  • GitHub Check: ci (Testcontainers.Azurite, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.CockroachDb, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.ClickHouse, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.Bigtable, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.ArangoDb, ubuntu-24.04)
  • GitHub Check: analyze (csharp)
  • GitHub Check: ci (Testcontainers.Azurite, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.CockroachDb, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.Consul, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.ClickHouse, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.Bigtable, ubuntu-24.04)
  • GitHub Check: ci (Testcontainers.ArangoDb, ubuntu-24.04)
  • GitHub Check: analyze (csharp)
🔇 Additional comments (12)
src/Testcontainers/Configurations/AuthConfigs/DockerEndpointAuthenticationConfiguration.cs (1)

23-23: LGTM - Reasonable timeout increase for Docker Engine v29 compatibility.

The 5x increase in the default named pipe connection timeout (1s → 5s) is a sensible workaround for Docker Engine v29 compatibility issues discovered during testing. The fallback default only applies when neither environment variables nor properties file configuration provide an explicit value, and users retain full control to override this timeout if needed.

tests/Testcontainers.Platform.Windows.Tests/.runs-on (1)

1-1: LGTM! Windows runner update aligns with the ltsc2025 image upgrade.

The update to the windows-2025 runner is consistent with the ServerCore image update to ltsc2025 in CommonImages.cs and supports Docker Engine v29 testing.

build/Tasks.cs (1)

19-21: LGTM! Well-documented timeout adjustment for uncached images.

The timeout increase from 5 to 10 minutes is appropriate given that the windows-2025 runner no longer has pre-cached images. The explanatory comments clearly justify this change.

tests/Testcontainers.Tests/Unit/Containers/Unix/TestcontainersContainerTest.cs (1)

92-97: LGTM! Network attachment is required for MAC address configuration.

The addition of a network to the MacAddress test is correct. In Docker, MAC addresses are assigned to network interfaces, so a container must be attached to a network for the MAC address to be properly configured. This change aligns with the updated network configuration logic in ContainerConfigurationConverter.cs.

tests/Testcontainers.Commons/CommonImages.cs (1)

18-18: LGTM! ServerCore image update aligns with Windows test environment.

The update from ltsc2022 to ltsc2025 is consistent with the Windows runner update and is appropriate for testing Docker Engine v29 support on Windows.

.github/workflows/test-report.yml (1)

33-33: Update to dorny/test-reporter@v2.3.0 is safe to merge.

Version 2.3.0 includes a fix for short summary formatting when a report title is present and Python support based on Java JUnit parser. No breaking changes are present, and the update represents incremental improvements to the action. The parameter configuration remains compatible.

.devcontainer/devcontainer.json (1)

16-17: No changes needed. The final version of .NET 10.0 has been available free of charge since the evening of November 11, 2025, and it is supported for three years as a long-term support (LTS) release. The devcontainer update to .NET 10.0 is appropriate and stable for development.

Directory.Packages.props (1)

8-9: Version 3.131.1 does not exist on public NuGet and the API versioning claim is incorrect.

The latest published version of Docker.DotNet.Enhanced is 3.128.1. Version 3.131.1 cannot be verified as existing or published.

More critically, the package uses SemVer format where the MINOR segment indicates the Docker Remote API version support—for instance v3.125 supports API v1.25. Following this scheme, version 3.131.1 would support API v1.31, not v1.52 as claimed. Docker Engine v29 requires API v1.52, which would require a version like 3.152.x under the current versioning scheme.

This update requires clarification on the actual package version being used and verification of its Docker Engine API compatibility.

Likely an incorrect or invalid review comment.

src/Testcontainers/Clients/ContainerConfigurationConverter.cs (1)

100-101: Add test coverage for multi-network EndpointSettings behavior and clarify design intent.

The code reuses a single EndpointSettings instance across all networks. While Docker API v1.44+ supports per-network MacAddress and Aliases configuration, the test suite lacks any coverage for multi-network scenarios. Add tests demonstrating that reusing the same EndpointSettings instance is the intended behavior, or implement per-network configuration if different networks should support distinct endpoint settings.

src/Testcontainers/Clients/TraceProgress.cs (3)

19-23: Error handling prioritized correctly.

Moving error logging before the debug level check ensures errors are always logged regardless of the configured log level. This is the correct behavior.


25-28: Early exit improves performance.

Checking the log level early and returning prevents unnecessary computation when debug logging is disabled.


36-40: Progress percentage calculation is safe and informative.

The percentage calculation is protected by the Total > 0 check, preventing division by zero. The enhanced formatting provides better visibility into progress.

@HofmeisterAn HofmeisterAn merged commit cd2f52a into develop Dec 20, 2025
148 checks passed
@HofmeisterAn HofmeisterAn deleted the feature/test-docker-engine-v29 branch December 20, 2025 17:23
@HofmeisterAn HofmeisterAn added the breaking change Causing compatibility issues label Jan 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

breaking change Causing compatibility issues enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants