diff --git a/cli/command/cli.go b/cli/command/cli.go index eb69b3eb73fc..7df2078b642d 100644 --- a/cli/command/cli.go +++ b/cli/command/cli.go @@ -466,6 +466,16 @@ func (cli *DockerCli) DockerEndpoint() docker.Endpoint { return cli.dockerEndpoint } +// DaemonHost returns the configured daemon endpoint. For connection helpers, +// the API client's host is an internal HTTP placeholder, so use the original +// endpoint when it is available. +func DaemonHost(cli Cli) string { + if host := cli.DockerEndpoint().Host; host != "" { + return host + } + return cli.Client().DaemonHost() +} + func (cli *DockerCli) getDockerEndPoint() (ep docker.Endpoint, err error) { cn := cli.CurrentContext() if cn == DefaultContextName { diff --git a/cli/command/container/client_test.go b/cli/command/container/client_test.go index 7c38e7bec8d6..d340f5ef5d65 100644 --- a/cli/command/container/client_test.go +++ b/cli/command/container/client_test.go @@ -27,6 +27,7 @@ func (e fakeStreamResult) Close() error { return e.ReadCloser.Clos type fakeClient struct { client.Client + daemonHost string inspectFunc func(string) (client.ContainerInspectResult, error) execInspectFunc func(execID string) (client.ExecInspectResult, error) execCreateFunc func(containerID string, options client.ExecCreateOptions) (client.ExecCreateResult, error) @@ -55,6 +56,10 @@ type fakeClient struct { Version string } +func (f *fakeClient) DaemonHost() string { + return f.daemonHost +} + func (f *fakeClient) ContainerList(_ context.Context, options client.ContainerListOptions) (client.ContainerListResult, error) { if f.containerListFunc != nil { return f.containerListFunc(options) diff --git a/cli/command/container/create.go b/cli/command/container/create.go index 122d15e2e149..58d7f519dd7a 100644 --- a/cli/command/container/create.go +++ b/cli/command/container/create.go @@ -102,7 +102,7 @@ func runCreate(ctx context.Context, dockerCLI command.Cli, flags *pflag.FlagSet, StatusCode: 125, } } - proxyConfig := dockerCLI.ConfigFile().ParseProxyConfig(dockerCLI.Client().DaemonHost(), opts.ConvertKVStringsToMapWithNil(copts.env.GetSlice())) + proxyConfig := dockerCLI.ConfigFile().ParseProxyConfig(command.DaemonHost(dockerCLI), opts.ConvertKVStringsToMapWithNil(copts.env.GetSlice())) newEnv := make([]string, 0, len(proxyConfig)) for k, v := range proxyConfig { if v == nil { diff --git a/cli/command/container/create_test.go b/cli/command/container/create_test.go index 1c6ec9264975..963b98f24d50 100644 --- a/cli/command/container/create_test.go +++ b/cli/command/container/create_test.go @@ -13,6 +13,7 @@ import ( "github.com/docker/cli/cli" "github.com/docker/cli/cli/config/configfile" + "github.com/docker/cli/cli/context/docker" "github.com/docker/cli/internal/test" "github.com/google/go-cmp/cmp" "github.com/moby/moby/api/types/container" @@ -311,6 +312,33 @@ func TestCreateContainerWithProxyConfig(t *testing.T) { assert.NilError(t, err) } +func TestCreateContainerWithSSHHostProxyConfig(t *testing.T) { + const ( + sshHost = "ssh://daemon.example.com" + dummyHost = "http://docker.example.com" + ) + + fakeCLI := test.NewFakeCli(&fakeClient{ + daemonHost: dummyHost, + createContainerFunc: func(options client.ContainerCreateOptions) (client.ContainerCreateResult, error) { + assert.Check(t, is.Contains(options.Config.Env, "HTTP_PROXY=http://ssh-proxy.example.com")) + return client.ContainerCreateResult{}, nil + }, + }) + fakeCLI.SetDockerEndpoint(docker.Endpoint{EndpointMeta: docker.EndpointMeta{Host: sshHost}}) + fakeCLI.SetConfigFile(&configfile.ConfigFile{ + Proxies: map[string]configfile.ProxyConfig{ + "default": {HTTPProxy: "http://default-proxy.example.com"}, + sshHost: {HTTPProxy: "http://ssh-proxy.example.com"}, + }, + }) + + cmd := newCreateCommand(fakeCLI) + cmd.SetOut(io.Discard) + cmd.SetArgs([]string{"image:tag"}) + assert.NilError(t, cmd.Execute()) +} + type fakeNotFound struct{} func (fakeNotFound) NotFound() {} diff --git a/cli/command/container/run.go b/cli/command/container/run.go index 3c25630d6b78..a4be2bec41de 100644 --- a/cli/command/container/run.go +++ b/cli/command/container/run.go @@ -91,7 +91,7 @@ func runRun(ctx context.Context, dockerCLI command.Cli, flags *pflag.FlagSet, ro StatusCode: 125, } } - proxyConfig := dockerCLI.ConfigFile().ParseProxyConfig(dockerCLI.Client().DaemonHost(), opts.ConvertKVStringsToMapWithNil(copts.env.GetSlice())) + proxyConfig := dockerCLI.ConfigFile().ParseProxyConfig(command.DaemonHost(dockerCLI), opts.ConvertKVStringsToMapWithNil(copts.env.GetSlice())) newEnv := []string{} for k, v := range proxyConfig { if v == nil { diff --git a/cli/command/image/build.go b/cli/command/image/build.go index db33e0e7c64d..a3385f44c75a 100644 --- a/cli/command/image/build.go +++ b/cli/command/image/build.go @@ -434,7 +434,7 @@ func imageBuildOptions(dockerCli command.Cli, options buildOptions) client.Image CgroupParent: options.cgroupParent, ShmSize: options.shmSize.Value(), Ulimits: options.ulimits.GetList(), - BuildArgs: configFile.ParseProxyConfig(dockerCli.Client().DaemonHost(), opts.ConvertKVStringsToMapWithNil(options.buildArgs.GetSlice())), + BuildArgs: configFile.ParseProxyConfig(command.DaemonHost(dockerCli), opts.ConvertKVStringsToMapWithNil(options.buildArgs.GetSlice())), Labels: opts.ConvertKVStringsToMap(options.labels.GetSlice()), CacheFrom: options.cacheFrom, SecurityOpt: options.securityOpt,