# FluentDocker for .NET container integration and test setup

> FluentDocker gives C# projects a fluent API for Docker and Podman containers, Compose resources, Kubernetes manifests, and test fixtures. It is most relevant to .NET integration tests and application code that needs to manage container lifecycles without writing every CLI operation by hand.

**mariotoffia/FluentDocker** — Use docker/podman, compose local and remote via a FluentAPI

- Repository: https://github.com/mariotoffia/FluentDocker
- Stars: 1,387 · Forks: 104
- Language: C#
- License: Apache-2.0
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/mariotoffia-fluentdocker

## FluentDocker targets C# code that manages containers

FluentDocker addresses a specific boundary in .NET development: code that must create, start, inspect, connect to, or remove Docker and Podman resources. The target audience includes developers building integration tests, local service harnesses, and applications whose normal runtime steps depend on containers. Instead of constructing command-line arguments and parsing text output at each call site, a developer can describe a container, network, image build, Compose stack, or Kubernetes play operation through fluent C# builders.

The library does not position itself as a replacement for container engines or Compose files. It remains a control layer for Docker and Podman. A typical use starts an nginx container, waits for port 80 to become reachable, reads the host-exposed endpoint, and disposes the returned resources when their lifetime ends. That is a close match for test fixtures and setup code, where container readiness and cleanup are important parts of the contract.

The README also shows xUnit, MSTest, and NUnit adapter packages. This makes FluentDocker relevant to teams that want container-backed test dependencies expressed in their existing test framework rather than managed by separate shell scripts. It is less convincing for a deployment tool whose primary interface is YAML and whose operators already use standard Docker or Podman command workflows, because those files remain the canonical engine interfaces.

## A kernel routes builders across Docker and Podman drivers

The documented architecture centers on a kernel created through `FluentDockerKernel.Create()`. Driver registrations are named during kernel construction, and a builder can then select a registered driver with calls such as `WithinDockerCli("docker", kernel)` or `WithinPodmanCli("podman", kernel)`. The same application can register Docker CLI and Podman CLI, which is useful when a codebase must support more than one local container engine.

FluentDocker lists Docker CLI, Docker API, and Podman CLI as its shipped drivers. Builders then return domain results such as `Containers`, `ComposeServices`, `Networks`, and images. This shared shape lets higher-level code reason about resources without switching to unrelated API conventions for each example. The interface names shown for drivers include `IContainerDriver` and `IImageDriver`; the README begins naming a network interface when its driver section is truncated.

The API is async-first in version 3, and the quick-start container and Compose examples use `BuildAsync()`. Some feature snippets also show synchronous `Build()` calls. That mixed presentation reflects the breadth of the current documentation, but it is an adoption concern: developers should confirm which methods belong to FluentDocker 3.1.0 rather than assume that every older pattern from the repository examples is interchangeable. Driver failures and CLI availability still propagate through the underlying tools. FluentDocker does not isolate the operating-system-specific behavior of Docker or Podman itself.

## Installing FluentDocker and running an nginx container

The README directs users to install the core package through the .NET CLI. Test users choose only the adapter package for their framework. This produces code-level integration with FluentDocker, but it does not install Docker or Podman.

```bash
dotnet add package FluentDocker
```

After that command, the project has the core `FluentDocker` reference. A test project can add the matching adapter instead of, or in addition to, the core package according to the package's role. The three documented adapter commands are shown here:

```bash
dotnet add package FluentDocker.Testing.Xunit
dotnet add package FluentDocker.Testing.MsTest
dotnet add package FluentDocker.Testing.NUnit
```

The first real use registers engines and creates a container. The following example assumes that the `docker` command is available and that the `nginx:alpine` image can be resolved:

```csharp
using System.Linq;
using FluentDocker.Builders;
using FluentDocker.Kernel;

using var kernel = await FluentDockerKernel.Create()
    .WithDockerCli("docker", d => d.AsDefault())
    .BuildAsync();

await using var results = await new Builder()
    .WithinDockerCli("docker", kernel)
    .UseContainer(c => c
        .UseImage("nginx:alpine")
        .ExposePort("80")
        .WaitForPort("80/tcp", 30000))
    .BuildAsync();
```

`WaitForPort("80/tcp", 30000)` makes startup dependent on a documented readiness condition rather than an arbitrary pause. The README then resolves the engine-selected host endpoint and prints it. Readers should see the address and port only after the container has reached the requested port state. If the CLI is missing, the image cannot be obtained, or the port does not become ready within the configured timeout, this flow cannot produce the endpoint.

## Compose, readiness, ports, and resource inspection

FluentDocker covers more than single-container creation. The Docker Compose example consumes an existing `docker-compose.yml`, enables orphan removal and waiting, and sets a timeout through `.WithWaitTimeout(30)`. This preserves Compose as the stack definition while letting C# control startup and return access to `ComposeServices`. The Podman example instead calls the documented Kubernetes driver interface for `kube play` and `kube down`, using `KubePlayConfig` with `YamlPath` and `Replace`.

Readiness is explicit rather than inferred from whether a start command returned. FluentDocker documents waits for a port, a named process, or a log message, each with a timeout. That matters for tests because a running container can still be unable to accept connections or may still be initializing an application. The tradeoff is that each wait condition becomes part of the test's behavior, and an unsuitable condition can delay failure until timeout.

Ports can be explicit or engine-selected. `.ExposePort(8080, 80)` maps host port 8080 to container port 80, while `.ExposePort("80")` lets the engine choose the host port. Callers use `ToHostExposedEndpoint("80/tcp")` to discover the result. This avoids hard-coding a random host port, but it also means that application configuration should consume the discovered endpoint rather than assume port 80 is available on the host.

Resource operations include configuration retrieval, asynchronous statistics, networks with static IPv4 addresses, host and named-volume mounts, file copies in either direction, and inline Dockerfile construction. These are useful integration-test primitives. They also widen the surface exposed to engine-specific differences, particularly across Docker CLI, Docker API, and Podman CLI.

## FluentDocker has real boundaries around engines and version changes

The largest limitation is that FluentDocker is not a self-contained container runtime. The documented CLI examples invoke executable names such as `docker` and `podman`, and the Podman setup can request automatic machine startup. The host must therefore provide the relevant tool, permissions, engine configuration, image access, and supported platform behavior. A C# API cannot compensate for a missing runtime. This is a poor fit for hermetic unit tests that prohibit Docker or Podman, and for deployment pipelines that expect one managed binary with no external engine dependency.

Port, process, and log waits also have predictable failure boundaries. The examples pass a timeout in milliseconds, but the documentation does not claim a guaranteed cleanup policy after readiness failure or describe engine-level rollback for every resource. The README does not document transaction semantics across a partially created Compose stack. Teams should inspect the API behavior for the specific builder version instead of assuming all resources will be removed automatically after an exception.

Upgrade cost is visible in the project's own version history. Version 3.0.0 is identified as a major rewrite with a multi-driver kernel, async-first API, Podman support, new test packages, and breaking changes. Releases `3.0.1` and `3.1.0` followed in May and June 2026. The README directs existing users to `docs/migration.md` and the `3.0.0` release notes. Those files should be checked before changing an established suite because code written for the earlier API may require more than package-version updates.

FluentDocker is distributed under `Apache-2.0`. That license is recorded in the repository and surfaced in the README, but organizations should review its notice and attribution obligations for the way they distribute or package the library. This is a compliance check, not a substitute for legal advice.

## Direct CLI scripts remain the clearer alternative for simple operations

The most direct alternative is to invoke Docker Compose or the selected engine from shell scripts, PowerShell, Make, or a CI runner. That approach follows the tools' native command interface and keeps C# outside container setup. It is a reasonable choice for a small number of stable operations, especially when the same commands already form part of a deployment workflow.

FluentDocker differs by expressing those operations as typed C# builders and returning container, service, network, and image results. Test code can select resources, call inspection methods, discover exposed endpoints, and combine readiness conditions without repeatedly parsing command output. Adapter packages connect that lifecycle with xUnit, MSTest, or NUnit fixtures. This approach has more C# API surface to learn, but it fits .NET test code that already needs resource objects and deterministic setup.

Raw CLI automation does not provide FluentDocker's fluent resource model, while FluentDocker does not eliminate the need for `docker-compose.yml`, container images, CLI programs, or compatible engine configuration. Choosing between them is therefore a boundary decision: use direct commands for simple operational scripts, and use FluentDocker when container state must participate in typed .NET control flow.

## Conclusion

Adopt FluentDocker when a .NET application or test suite needs programmatic Docker or Podman lifecycle management through a typed API. Do not choose it for environments where the required CLI is unavailable or an in-process library would be preferable. Before adoption, verify the adapter package against the chosen test framework, confirm that Docker or Podman can run on the build host, and review `docs/migration.md` if upgrading from a pre-3.0 release.

## FAQ

### Which .NET versions does FluentDocker target?

The README badge lists `.NET net8.0 | net10.0`. The repository also contains `global.json`, but its contents are not documented in the README excerpt.

### Does FluentDocker work with Podman as well as Docker?

Yes. The quick start registers Podman CLI, creates containers through `WithinPodmanCli`, and documents `kube play` and `kube down` through its Podman Kubernetes driver.

### Does installing the FluentDocker NuGet package install Docker or Podman?

No. The documented installation commands install FluentDocker packages, while the examples still reference external executables named `docker` or `podman`.

## Sources

- [Issues](https://github.com/mariotoffia/FluentDocker/issues)
- [License: Apache-2.0](https://github.com/mariotoffia/FluentDocker/blob/master/LICENSE)
- [mariotoffia/FluentDocker on GitHub](https://github.com/mariotoffia/FluentDocker)
- [README](https://github.com/mariotoffia/FluentDocker/blob/master/README.md)
- [Releases](https://github.com/mariotoffia/FluentDocker/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/mariotoffia-fluentdocker
