Skip to content
Merged
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
26 changes: 22 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,21 @@ dotnet add package Docker.DotNet.Enhanced

## Usage

You can initialize the client as follows:
### Default client (Docker CLI–style resolution)

`new DockerClientBuilder()` resolves the Docker endpoint the same way the `docker` CLI does. This works the same on Linux, macOS, and Windows:

1. **Environment variables**: `DOCKER_HOST`, if set.
2. **Docker context**: the active context from `DOCKER_CONTEXT`, or from the `currentContext` field in `~/.docker/config.json` (`%USERPROFILE%\.docker\config.json` on Windows). For a named context, the endpoint is read from `~/.docker/contexts/meta/<sha256(name)>/meta.json`. `DOCKER_CONFIG` is honored if set.
3. **Platform default**: used when neither `DOCKER_HOST` nor a non-default context is configured: `unix:///var/run/docker.sock` on Linux/macOS, `npipe://./pipe/docker_engine` on Windows.

```csharp
using Docker.DotNet;
var client = new DockerClientBuilder()
.Build();
```

### Explicit endpoint

```csharp
using Docker.DotNet;
Expand All @@ -64,21 +78,25 @@ var client = new DockerClientBuilder()
```csharp
using Docker.DotNet;
var client = new DockerClientBuilder()
.WithEndpoint(new Uri("unix:/var/run/docker.sock"))
.WithEndpoint(new Uri("unix:///var/run/docker.sock"))
.Build();
```

**Note:**
For HTTP(S) connections or special authentication types (e.g. X509, BasicAuth), see the corresponding sections below.

To connect to your local [Docker Desktop on Windows](https://docs.docker.com/desktop/setup/install/windows-install/) instance via named pipe or your local [Docker Desktop on Mac](https://docs.docker.com/desktop/setup/install/mac-install/) instance via Unix socket:
### Specific Docker context by name

Use `WithContext` to target a context by name. The endpoint is read from `~/.docker/contexts/meta/<sha256(name)>/meta.json`:

```csharp
using Docker.DotNet;
var client = new DockerClientBuilder()
.WithContext("desktop-linux")
.Build();
```

`ssh://` endpoints (from SSH-based Docker contexts) are not supported. To connect to a remote daemon over SSH, set up an SSH tunnel and point `DOCKER_HOST` (or a context) at the forwarded socket.

### Enabling .NET Native HTTP Handler

**Experimental**: To enhance the communication between your application and the Docker Engine, you can enable the .NET native (socket) HTTP handler.
Expand Down
1 change: 1 addition & 0 deletions src/Docker.DotNet/Docker.DotNet.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
<Using Include="System.Runtime.InteropServices" />
<Using Include="System.Runtime.Serialization" />
<Using Include="System.Security.Authentication" />
<Using Include="System.Security.Cryptography" />
<Using Include="System.Security.Cryptography.X509Certificates" />
<Using Include="System.Text" />
<Using Include="System.Text.Json" />
Expand Down
71 changes: 60 additions & 11 deletions src/Docker.DotNet/DockerClientBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,37 @@ public class DockerClientBuilder
{
private static readonly bool NativeHttpEnabled = Environment.GetEnvironmentVariable("DOCKER_DOTNET_NATIVE_HTTP_ENABLED") == "1";

private static readonly Uri LocalDockerEndpoint = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? new Uri("npipe://./pipe/docker_engine") : new Uri("unix:/var/run/docker.sock");
private readonly DockerConfig _dockerConfig;

/// <summary>
/// Initializes a new instance of the <see cref="DockerClientBuilder"/> class.
/// </summary>
/// <remarks>
/// Defaults to <c>npipe://./pipe/docker_engine</c> on Windows and <c>unix:/var/run/docker.sock</c> on Linux/macOS.
/// Resolves the Docker endpoint using the same precedence as the <c>docker</c> CLI.
///
/// First, the value of <c>DOCKER_HOST</c> is used when it is set.
///
/// If no host is specified, the active Docker context is used. The context is
/// determined from <c>DOCKER_CONTEXT</c> or from <c>currentContext</c> in
/// <c>~/.docker/config.json</c>.
///
/// When neither a host nor a context is configured, the platform default
/// endpoint is used: <c>unix:///var/run/docker.sock</c> on Linux and macOS
/// and <c>npipe://./pipe/docker_engine</c> on Windows.
/// </remarks>
public DockerClientBuilder()
: this(DockerConfig.Instance)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="DockerClientBuilder"/> class.
/// </summary>
/// <param name="dockerConfig">The Docker config to preserve.</param>
public DockerClientBuilder(
DockerConfig dockerConfig)
: this(dockerConfig, new ClientOptions { Endpoint = dockerConfig.GetEndpoint() }, NullLogger.Instance)
{
_ = WithEndpoint(LocalDockerEndpoint);
}

/// <summary>
Expand All @@ -30,20 +50,35 @@ public DockerClientBuilder()
protected DockerClientBuilder(
ClientOptions clientOptions,
ILogger logger)
: this(DockerConfig.Instance, clientOptions, logger)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="DockerClientBuilder"/> class.
/// </summary>
/// <param name="dockerConfig">The Docker config to preserve.</param>
/// <param name="clientOptions">The client options to preserve.</param>
/// <param name="logger">The logger to preserve.</param>
protected DockerClientBuilder(
DockerConfig dockerConfig,
ClientOptions clientOptions,
ILogger logger)
{
_dockerConfig = dockerConfig;
ClientOptions = clientOptions;
Logger = logger;
}

/// <summary>
/// Gets the client options.
/// </summary>
protected ClientOptions ClientOptions { get; private set; } = new();
protected ClientOptions ClientOptions { get; private set; }

/// <summary>
/// Gets the logger.
/// </summary>
protected ILogger Logger { get; private set; } = NullLogger.Instance;
protected ILogger Logger { get; private set; }

/// <summary>
/// Sets the Docker Engine API version to request.
Expand All @@ -67,6 +102,19 @@ public DockerClientBuilder WithEndpoint(Uri endpoint)
return this;
}

/// <summary>
/// Sets the Docker endpoint declared by the named Docker context.
/// </summary>
/// <remarks>
/// Reads the endpoint from <c>~/.docker/contexts/meta/&lt;sha256(name)&gt;/meta.json</c>.
/// </remarks>
/// <param name="contextName">The context name (e.g. <c>desktop-linux</c>).</param>
/// <returns>The builder instance.</returns>
public DockerClientBuilder WithContext(string contextName)
{
return WithEndpoint(_dockerConfig.GetEndpoint(contextName));
}

/// <summary>
/// Sets the authentication provider used to configure the HTTP handler.
/// </summary>
Expand Down Expand Up @@ -153,7 +201,7 @@ public DockerClientBuilder WithLogger(ILogger logger)
/// <returns>A typed builder that uses the legacy HTTP transport.</returns>
public DockerClientBuilder<LegacyHttpTransportOptions> WithTransportOptions(LegacyHttpTransportOptions transportOptions)
{
return new DockerClientBuilder<LegacyHttpTransportOptions>(LegacyHttp.DockerHandlerFactory.Instance, transportOptions, ClientOptions, Logger);
return new DockerClientBuilder<LegacyHttpTransportOptions>(LegacyHttp.DockerHandlerFactory.Instance, transportOptions, _dockerConfig, ClientOptions, Logger);
}

/// <summary>
Expand All @@ -163,7 +211,7 @@ public DockerClientBuilder<LegacyHttpTransportOptions> WithTransportOptions(Lega
/// <returns>A typed builder that uses the native HTTP transport.</returns>
public DockerClientBuilder<NativeHttpTransportOptions> WithTransportOptions(NativeHttpTransportOptions transportOptions)
{
return new DockerClientBuilder<NativeHttpTransportOptions>(NativeHttp.DockerHandlerFactory.Instance, transportOptions, ClientOptions, Logger);
return new DockerClientBuilder<NativeHttpTransportOptions>(NativeHttp.DockerHandlerFactory.Instance, transportOptions, _dockerConfig, ClientOptions, Logger);
}

/// <summary>
Expand All @@ -173,7 +221,7 @@ public DockerClientBuilder<NativeHttpTransportOptions> WithTransportOptions(Nati
/// <returns>A typed builder that uses the named pipe transport.</returns>
public DockerClientBuilder<NPipeTransportOptions> WithTransportOptions(NPipeTransportOptions transportOptions)
{
return new DockerClientBuilder<NPipeTransportOptions>(NPipe.DockerHandlerFactory.Instance, transportOptions, ClientOptions, Logger);
return new DockerClientBuilder<NPipeTransportOptions>(NPipe.DockerHandlerFactory.Instance, transportOptions, _dockerConfig, ClientOptions, Logger);
}

/// <summary>
Expand All @@ -183,19 +231,19 @@ public DockerClientBuilder<NPipeTransportOptions> WithTransportOptions(NPipeTran
/// <returns>A typed builder that uses the Unix socket transport.</returns>
public DockerClientBuilder<UnixSocketTransportOptions> WithTransportOptions(UnixSocketTransportOptions transportOptions)
{
return new DockerClientBuilder<UnixSocketTransportOptions>(Unix.DockerHandlerFactory.Instance, transportOptions, ClientOptions, Logger);
return new DockerClientBuilder<UnixSocketTransportOptions>(Unix.DockerHandlerFactory.Instance, transportOptions, _dockerConfig, ClientOptions, Logger);
}

/// <summary>
/// Selects a custom transport by providing a handler factory and transport-specific options.
/// Selects custom transport by providing a handler factory and transport-specific options.
/// </summary>
/// <typeparam name="TTransportOptions">The type of transport options consumed by the custom handler factory.</typeparam>
/// <param name="transportFactory">The custom transport handler factory.</param>
/// <param name="transportOptions">The transport-specific options passed to the custom handler factory.</param>
/// <returns>A typed builder that uses the provided custom transport.</returns>
public DockerClientBuilder<TTransportOptions> WithTransportOptions<TTransportOptions>(IDockerHandlerFactory<TTransportOptions> transportFactory, TTransportOptions transportOptions)
{
return new DockerClientBuilder<TTransportOptions>(transportFactory, transportOptions, ClientOptions, Logger);
return new DockerClientBuilder<TTransportOptions>(transportFactory, transportOptions, _dockerConfig, ClientOptions, Logger);
}

/// <summary>
Expand Down Expand Up @@ -230,6 +278,7 @@ protected virtual IDockerHandlerFactory ResolveTransportFactory(string scheme)
"tcp" or "http" or "https" => NativeHttpEnabled
? NativeHttp.DockerHandlerFactory.Instance
: LegacyHttp.DockerHandlerFactory.Instance,
"ssh" => throw new SshDockerEndpointNotSupportedException(),
_ => throw new NotSupportedException($"The URI scheme '{scheme}' is not supported.")
};
}
Expand Down
21 changes: 20 additions & 1 deletion src/Docker.DotNet/DockerClientBuilder`1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public sealed class DockerClientBuilder<TTransportOptions> : DockerClientBuilder
public DockerClientBuilder(
IDockerHandlerFactory<TTransportOptions> transportFactory,
TTransportOptions transportOptions)
: base()
{
_transportFactory = transportFactory;
_transportOptions = transportOptions;
Expand All @@ -28,19 +29,37 @@ public DockerClientBuilder(
/// </summary>
/// <param name="transportFactory">The transport handler factory.</param>
/// <param name="transportOptions">The transport options.</param>
/// <param name="dockerConfig">The Docker config to preserve.</param>
/// <param name="clientOptions">The client options to preserve.</param>
/// <param name="logger">The logger to preserve.</param>
public DockerClientBuilder(
IDockerHandlerFactory<TTransportOptions> transportFactory,
TTransportOptions transportOptions,
DockerConfig dockerConfig,
ClientOptions clientOptions,
ILogger logger)
: base(clientOptions, logger)
: base(dockerConfig, clientOptions, logger)
{
_transportFactory = transportFactory;
_transportOptions = transportOptions;
}

/// <summary>
/// Initializes a new instance of the <see cref="DockerClientBuilder{TTransportOptions}"/> class.
/// </summary>
/// <param name="transportFactory">The transport handler factory.</param>
/// <param name="transportOptions">The transport options.</param>
/// <param name="clientOptions">The client options to preserve.</param>
/// <param name="logger">The logger to preserve.</param>
public DockerClientBuilder(
IDockerHandlerFactory<TTransportOptions> transportFactory,
TTransportOptions transportOptions,
ClientOptions clientOptions,
ILogger logger)
: this(transportFactory, transportOptions, DockerConfig.Instance, clientOptions, logger)
{
}

/// <summary>
/// Builds a <see cref="DockerClient"/> using the explicitly selected transport handler.
/// </summary>
Expand Down
Loading