Napbat.Testcontainers.Build 0.1.0

dotnet add package Napbat.Testcontainers.Build --version 0.1.0
                    
NuGet\Install-Package Napbat.Testcontainers.Build -Version 0.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Napbat.Testcontainers.Build" Version="0.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Napbat.Testcontainers.Build" Version="0.1.0" />
                    
Directory.Packages.props
<PackageReference Include="Napbat.Testcontainers.Build" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Napbat.Testcontainers.Build --version 0.1.0
                    
#r "nuget: Napbat.Testcontainers.Build, 0.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Napbat.Testcontainers.Build@0.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Napbat.Testcontainers.Build&version=0.1.0
                    
Install as a Cake Addin
#tool nuget:?package=Napbat.Testcontainers.Build&version=0.1.0
                    
Install as a Cake Tool

Testcontainers.Build

Build Docker images from folders, HTTP(S) build contexts, or Git repositories. Use the images with Testcontainers in C# or Rust, without first publishing your application image to GHCR or another registry.

Both libraries provide fluent requests, replaceable providers and build backends, and explicit resource ownership. Docker can still download base images and the Testcontainers resource reaper.

Component Name
NuGet package Napbat.Testcontainers.Build
C# namespace Testcontainers.Build
Rust crate testcontainers-build (import as testcontainers_build)
Image builder in both libraries ImageBuilder

Run the examples

Run these commands from the repository root:

dotnet run --project dotnet/examples/Testcontainers.Build.Examples -- local
dotnet run --project dotnet/examples/Testcontainers.Build.Examples -- remote
dotnet run --project dotnet/examples/Testcontainers.Build.Examples -- git

cargo run -p testcontainers-build --example local
cargo run -p testcontainers-build --example remote
cargo run -p testcontainers-build --example git-source

Each example builds an image, starts a container, waits for readiness, checks its files, and removes the container and image.

Example Source and features
Local Sample folder; nested Dockerfile, build argument, target stage, disabled layer cache, timeout, and .dockerignore.
Remote Filtered tar archive served by a temporary HTTP container; Docker downloads the context over HTTP.
Git Temporary repository; pinned commit and checkout subdirectory. The checkout is removed after the build.

Browse the C# examples or Rust examples. Both use the shared example context.

Prerequisites

  • Docker CLI with buildx and a running Linux container engine.
  • Git on PATH for Git sources and the Git examples.
  • .NET SDK 10 and the .NET 8 runtime for the C# solution and examples.
  • A current stable Rust toolchain. The last full verification used Rust 1.98.

The Docker CLI and Testcontainers must use the same daemon. Configure DOCKER_HOST when needed; do not assume a Docker CLI context change also changes Testcontainers. The remote example uses host.docker.internal on Docker Desktop and 127.0.0.1 on Linux. Set TESTCONTAINERS_BUILD_HTTP_HOST if your builder needs another address.

Use the libraries

For C#, reference Testcontainers.Build.csproj or a locally built NuGet package. For Rust, add a path dependency on rust/testcontainers-build. Add testcontainers = "0.28" and Tokio when using its native container API. See package commands.

C# fluent API

This snippet uses the sample context when run from the repository root:

using DotNet.Testcontainers.Builders;
using Testcontainers.Build;

await using var image = await new ImageBuilder()
    .WithSource(new FolderSource("rust/testcontainers-build/examples/context"))
    .WithDockerfile("container/Dockerfile")
    .WithBuildArgument("GREETING", "hello from C#")
    .WithTarget("runtime")
    .WithTimeout(TimeSpan.FromMinutes(2))
    .BuildAsync();

await using var container = image.ToContainerBuilder()
    .WithWaitStrategy(Wait.ForUnixContainer().UntilMessageIsLogged("example-ready"))
    .Build();
await container.StartAsync();
// Use the container here. Its disposal runs before image disposal.

Configuration methods return new requests. Reuse a common request to create independent variants. WithOptions copies caller-owned build arguments. Pass a cancellation token to BuildAsync to cancel resolution or the build. The direct BuildAsync(source, options, cancellationToken) API is also available.

Rust fluent API

In an async function, build the same context with:

use testcontainers_build::{FolderSource, ImageBuilder};

let mut image = ImageBuilder::default()
    .with_source(FolderSource::new("rust/testcontainers-build/examples/context"))
    .with_dockerfile("container/Dockerfile")
    .with_build_argument("GREETING", "hello from Rust")
    .with_target("runtime")
    .build()
    .await?;

// Configure native container wait conditions with image.image().
// Remove all containers before removing the image.
image.remove().await?;

Rust with_* methods consume and return the request. The direct build(&source, &options) API accepts borrowed inputs. See the Rust package README for a complete program and the example helper for container checks and cleanup on error paths.

Sources and build options

Source C# Rust
Folder new FolderSource(path) FolderSource::new(path)
HTTP(S) new RemoteUriSource(uri) RemoteUriSource::new(uri)?
Git new GitSource(new GitRequest(repository, revision, subdirectory)) GitSource::new(GitRequest::new(repository).with_revision(revision).with_subdirectory(subdirectory))

Supply the source to WithSource or with_source. Use a full Git commit ID for repeatable builds. Branches and tags can change.

Option C# method Rust method Default
Dockerfile WithDockerfile with_dockerfile Dockerfile, relative to the context
Build argument WithBuildArgument with_build_argument None; a repeated name replaces its value
Target stage WithTarget with_target Last Dockerfile stage
Platform WithPlatform with_platform Docker default
Disable layer cache WithNoCache with_no_cache Cache enabled
Timeout WithTimeout with_timeout Ten minutes, including source resolution
Replace all options WithOptions with_options A new BuildOptions value

Validation runs before source resolution. Use forward slashes for context-relative paths. Absolute paths, parent traversal, and symbolic links in the selected Git subdirectory or Dockerfile path are rejected. Docker handles other links in the context. Timeouts must be positive and at most 4,294,967,294 milliseconds.

Source behavior and cleanup

Folder sources use the caller's directory without copying or deleting it. Git sources fetch one revision into a temporary checkout and delete it after the build. The default Git provider uses Git's authentication configuration and disables terminal prompts. It does not explicitly initialize submodules or manage Git LFS. Use a custom provider when the checkout needs those steps.

HTTP(S) sources pass a URI to Docker. The builder must be able to reach it. The response can be a standard tar archive, optionally compressed with gzip, or a plain Dockerfile. ZIP is not supported. A plain remote Dockerfile has no local files for COPY.

Docker applies ignore rules to folder and Git contexts. Filter remote archives before creation: Docker uses the files already in the archive and does not apply its .dockerignore. The remote examples include only the required sample files.

Each build creates a unique local tag and can reuse Docker's layer cache. Image removal removes the owned tag; it does not prune shared caches or remove containers. Remove containers before their image.

  • C#: await using removes the image at scope exit. Declare the image before the container so disposal happens in the correct order.
  • Rust: call remove().await on success and error paths. Drop does not perform asynchronous image removal.

The C# adapter disables registry pulls. Rust Testcontainers 0.28 uses the local image first but can attempt a pull if it is missing. Keep the image available until all containers are removed.

Build errors include tool output. Do not put secrets in build arguments or URLs; tools can include them in diagnostics. C# cancellation stops the subprocess tree. Rust requests subprocess termination when its future is dropped, without a guarantee that all descendants stop.

External sources in the examples

dotnet run --project dotnet/examples/Testcontainers.Build.Examples -- remote https://example.com/context.tar.gz
dotnet run --project dotnet/examples/Testcontainers.Build.Examples -- git https://example.com/service.git COMMIT services/app

cargo run -p testcontainers-build --example remote -- https://example.com/context.tar.gz
cargo run -p testcontainers-build --example git-source -- https://example.com/service.git COMMIT services/app

These URLs and COMMIT are placeholders. Inputs must follow the sample contract: container/Dockerfile, a runtime stage, payload.txt, /message in the image, and an example-ready startup message. Checks expect the sample payload at /app/payload.txt and no /app/excluded.txt. Adapt the source and checks for your application. These are example requirements, not library restrictions.

Extension points

Responsibility C# Rust
Resolve a build context IBuildContextProvider BuildContextProvider
Check out Git IGitProvider GitProvider
Build and remove an image IImageBuildBackend ImageBuildBackend

Inject a Git provider into GitSource, or an image backend into ImageBuilder. This permits hosting APIs, checkout caches, and Docker Engine clients without changing orchestration. The default backend is DockerCliBackend.

Providers return BuildContext. In C#, supply a cleanup callback for owned resources. In Rust, use BuildContext::with_owner to retain a resource guard. The context stays alive until the backend finishes. Providers must honor C# cancellation tokens or Rust future cancellation.

Project layout and maintenance

Testcontainers.Build.slnx
Cargo.toml                         # workspace and lint policy
dotnet/
  Directory.Build.props
  src/Testcontainers.Build/
  tests/Testcontainers.Build.Tests/
  examples/Testcontainers.Build.Examples/
rust/testcontainers-build/
  Cargo.toml                       # inherits workspace lints
  src/lib.rs
  src/                             # focused modules
  tests/builders.rs
  tests/providers/main.rs
  tests/docker/main.rs
  tests/common/mod.rs
  examples/local/main.rs
  examples/remote/main.rs
  examples/git-source/main.rs
  examples/common/
  examples/context/                # shared with C# examples
spec/path-cases.json                # shared path contract
fixtures/app/                       # shared Docker test fixture

The Rust package follows the Cargo layout guide. The virtual workspace keeps generated files in target at the repository root. This library repository does not track Cargo.lock; Cargo generates it locally. Every member inherits Cargo.toml lint levels with [lints] workspace = true. See AGENTS.md for coding and documentation rules.

The implementations remain native. They share fixtures rather than generated async or resource-management code. A future declarative build manifest could provide a code generation boundary; no generator is required now.

Verify changes

These checks do not require Docker; Docker tests are skipped by default:

dotnet test Testcontainers.Build.slnx
dotnet format Testcontainers.Build.slnx --verify-no-changes --no-restore
cargo test --workspace
cargo fmt --all -- --check
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo doc --workspace --no-deps

Enable Docker tests in PowerShell:

$env:TESTCONTAINERS_BUILD_DOCKER_TESTS = "1"
dotnet test Testcontainers.Build.slnx
cargo test --workspace --test docker -- --ignored

In a POSIX shell, use TESTCONTAINERS_BUILD_DOCKER_TESTS=1 dotnet test Testcontainers.Build.slnx. Run the examples after changes to their behavior. CI runs tests, examples, lints, documentation, and package builds.

Build local packages

dotnet pack dotnet/src/Testcontainers.Build/Testcontainers.Build.csproj -c Release -o artifacts
cargo package -p testcontainers-build

The NuGet package goes to artifacts/. The Rust archive goes to target/package/ and includes the examples and their context. These commands do not publish packages.

Dependency compatibility

The NuGet package requires Testcontainers 4.14.0 or newer. This is a minimum version, not an exact pin. A compatible direct reference in the consuming project can satisfy the dependency without a second package version for that target.

The Rust crate uses testcontainers = "0.28", which permits versions from 0.28.0 up to, but excluding, 0.29.0. Use the same compatible range in an application that uses the native Testcontainers API. A different minor release can create duplicate crates with distinct types. Do not widen the range across breaking versions without verifying the adapter. See Cargo version requirements and NuGet resolution.

Publish packages

The publishing guide covers registry access, release versions, dry runs, and tag-based publishing. CI stores NuGet packages, symbols, and the Rust crate as downloadable artifacts. A dry run does not upload packages to a registry.

License

Both libraries use the MIT license.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.0 173 9/5/2026