fix: support Docker daemon over SSH (DOCKER_HOST=ssh://...)#3078
fix: support Docker daemon over SSH (DOCKER_HOST=ssh://...)#3078lucklove wants to merge 3 commits into
Conversation
| @@ -62,6 +63,10 @@ func NewClient(ctx context.Context, opts ...Option) (*apiClient, error) { | |||
| client.WithHost(clientOptions.host), | |||
| } | |||
|
|
|||
There was a problem hiding this comment.
This will break whenever DOCKER_CERT_PATH is set. WithTLSClientConfigFromEnv() has already installed TLS before this branch, and adding only the helper dialer preserves that configuration. The client then attempts a TLS handshake over docker system dial-stdio, which speaks plain Docker HTTP. Replace the transport with a non-TLS transport for the SSH path.
| @@ -62,6 +63,10 @@ func NewClient(ctx context.Context, opts ...Option) (*apiClient, error) { | |||
| client.WithHost(clientOptions.host), | |||
| } | |||
|
|
|||
There was a problem hiding this comment.
The helper returns Host specifically as the valid dummy HTTP origin for requests over its dialer, but it is never applied. Retaining ssh://user@host leaves an invalid HTTP Host, and a socket-path SSH URL has the same issue. This is especially visible when HTTP_PROXY is set, where Go rejects the invalid Host before opening SSH. Apply client.WithHost(helper.Host) and ensure proxy settings do not carry into connection-helper transports.
| @@ -62,6 +63,10 @@ func NewClient(ctx context.Context, opts ...Option) (*apiClient, error) { | |||
| client.WithHost(clientOptions.host), | |||
| } | |||
|
|
|||
There was a problem hiding this comment.
Please return this error instead of ignoring it. For an invalid SSH endpoint such as ssh://user:password@host or ssh://host?foo=bar, connhelper provides clear validation; ignoring it instead falls back to a malformed Docker client and surfaces an unrelated connection failure.
Configure the docker client entirely from connhelper for ssh:// hosts: - use helper.Host as the HTTP origin - install a non-TLS, proxy-disabled transport so DOCKER_CERT_PATH / HTTP_PROXY do not leak into the SSH path - return connhelper errors (invalid ssh URL) instead of silently falling through Covered by pkg/docker/docker_ssh_test.go: - invalid ssh URL (password / query) returns wrapped error - happy path pulls alpine:latest over DOCKER_HOST=ssh://root@kr - DOCKER_CERT_PATH + ssh host no longer breaks - HTTP_PROXY + ssh host no longer breaks
|
Pushed an updated revision that addresses all three inline comments. What changed in
Coverage (
The live subtests are gated by |
Problem
When
DOCKER_HOSTor the active Docker context is set to an SSH endpoint (e.g.ssh://user@host),cogfails with:The root cause is that the Docker Go SDK's
client.WithHost()does not understand thessh://scheme — it attempts a plain TCP/HTTP connection instead of tunneling over SSH.The standard
dockerCLI handles this transparently viaconnhelper.GetConnectionHelper(), which returns an SSH-based dialer forssh://hosts.Fix
After building the
dockerClientOptsslice, callconnhelper.GetConnectionHelper(host). If the host is an SSH URL, inject the returned SSH dialer viaclient.WithDialContext. This mirrors how the official Docker CLI handles remote SSH daemons.github.com/docker/cliis already a dependency, so no new dependencies are introduced.Testing
pkg/dockertests all passcog buildworks against a remote Docker daemon viaDOCKER_HOST=ssh://root@<host>