Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

On remote connect failure, docker erronously refers to "docker.example.com" #5604

Open
ilsaloving opened this issue Nov 7, 2024 · 2 comments

Comments

@ilsaloving
Copy link

Description

When trying to connect to a remote host, and the connection fails for whatever reason, it returns the error:

Error pinging Docker server: Cannot connect to the Docker daemon at http://docker.example.com. Is the docker daemon running?

I spent way too much time trying to figure out why docker was trying to connect to docker.example.com instead of my desired host, not realizing someone had just been lazy and chose not to write a proper error message.

Reproduce

  1. Set DOCKER_HOST to a valid server you can login to but doesn't have docker installed. eg: ssh://[email protected]
  2. Use any docker cli command, or the python library, to interact with docker

Expected behavior

No response

docker version

Client: Docker Engine - Community
Version: 27.3.1
API version: 1.47
Go version: go1.22.7
Git commit: ce12230
Built: Fri Sep 20 11:40:59 2024
OS/Arch: linux/amd64
Context: default

docker info

Client: Docker Engine - Community
Version: 27.3.1
Context: default
Debug Mode: false
Plugins:
buildx: Docker Buildx (Docker Inc.)
Version: v0.17.1
Path: /usr/libexec/docker/cli-plugins/docker-buildx

Additional Info

No response

@thaJeztah
Copy link
Member

Thanks for reporting

not realizing someone had just been lazy and chose not to write a proper error message.

Someone here is the Go stdlibrary 😂

A bit more context;

This error is produced by the go stdlib; the reason you get the docker.example.com domain to show up is that this part of the Go stdlib requires a validly formed host name to be set. I think at the time, the example.com domain was used for this (which is one of the designated special-purpose domains; https://www.rfc-editor.org/rfc/rfc6761.html) for the event where the domain would actualy be handled, it wouldn't be calling home or connecting to some other domain.

We recently had to add a similar "dummy" domain to the client code, after a breaking change in Go's stdlib forced a dummy domain to be used for other purposes. For that case we chose api.moby.localhost; we could probably use the same for this case; the code-comment outlines some of the technical details;

// DummyHost is a hostname used for local communication.
//
// It acts as a valid formatted hostname for local connections (such as "unix://"
// or "npipe://") which do not require a hostname. It should never be resolved,
// but uses the special-purpose ".localhost" TLD (as defined in [RFC 2606, Section 2]
// and [RFC 6761, Section 6.3]).
//
// [RFC 7230, Section 5.4] defines that an empty header must be used for such
// cases:
//
// If the authority component is missing or undefined for the target URI,
// then a client MUST send a Host header field with an empty field-value.
//
// However, [Go stdlib] enforces the semantics of HTTP(S) over TCP, does not
// allow an empty header to be used, and requires req.URL.Scheme to be either
// "http" or "https".
//
// For further details, refer to:
//
// - https://github.com/docker/engine-api/issues/189
// - https://github.com/golang/go/issues/13624
// - https://github.com/golang/go/issues/61076
// - https://github.com/moby/moby/issues/45935
//
// [RFC 2606, Section 2]: https://www.rfc-editor.org/rfc/rfc2606.html#section-2
// [RFC 6761, Section 6.3]: https://www.rfc-editor.org/rfc/rfc6761#section-6.3
// [RFC 7230, Section 5.4]: https://datatracker.ietf.org/doc/html/rfc7230#section-5.4
// [Go stdlib]: https://github.com/golang/go/blob/6244b1946bc2101b01955468f1be502dbadd6807/src/net/http/transport.go#L558-L569
const DummyHost = "api.moby.localhost"

I'm not 100% sure if we'd be able to fully rewrite the error-message, other than through string-matching, which may be too brittle (but it's worth looking into)

@ilsaloving
Copy link
Author

If you can't rewrite it, can you at least wrap it to include the hostname that the user actually provided?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants