From 6458766042a9a7d816c3a5df2bff3b8db4d593c2 Mon Sep 17 00:00:00 2001 From: Andrew Roberts Date: Sun, 17 May 2026 22:10:51 -0400 Subject: [PATCH] fix: support ssh:// DOCKER_HOST via connhelper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Docker Go SDK alone cannot dial ssh:// transports — that requires github.com/docker/cli/cli/connhelper, which the docker CLI wires up but cdebug was missing. Without it, DOCKER_HOST=ssh://user@host fails with `dial tcp: lookup user@host: no such host`. This resolves the effective host from opts.Host or DOCKER_HOST, runs it through connhelper.GetConnectionHelper, and wires up the SSH dialer when present. --- pkg/docker/client.go | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/pkg/docker/client.go b/pkg/docker/client.go index 52445a6e..45bf0f2e 100644 --- a/pkg/docker/client.go +++ b/pkg/docker/client.go @@ -4,7 +4,10 @@ import ( "context" "fmt" "io" + "net/http" + "os" + "github.com/docker/cli/cli/connhelper" "github.com/docker/cli/cli/streams" "github.com/docker/docker/api/types/image" "github.com/docker/docker/client" @@ -28,8 +31,28 @@ func NewClient(opts Options) (*Client, error) { client.FromEnv, client.WithAPIVersionNegotiation(), } - if len(opts.Host) > 0 { - dockerOpts = append(dockerOpts, client.WithHost(opts.Host)) + + host := opts.Host + if host == "" { + host = os.Getenv("DOCKER_HOST") + } + if host != "" { + helper, err := connhelper.GetConnectionHelper(host) + if err != nil { + return nil, fmt.Errorf("cannot resolve Docker connection helper: %w", err) + } + if helper != nil { + httpClient := &http.Client{ + Transport: &http.Transport{DialContext: helper.Dialer}, + } + dockerOpts = append(dockerOpts, + client.WithHTTPClient(httpClient), + client.WithHost(helper.Host), + client.WithDialContext(helper.Dialer), + ) + } else if opts.Host != "" { + dockerOpts = append(dockerOpts, client.WithHost(opts.Host)) + } } inner, err := client.NewClientWithOpts(dockerOpts...)