-
Notifications
You must be signed in to change notification settings - Fork 18.6k
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
Support host.docker.internal in dockerd on Linux #40007
Conversation
Looks Good. But I don't really understand the intent of this feature. Just to save the IP information of docker0? Is it the same effect when using environment variable records? If I understand wrong, please tell me. |
@tao12345666333 updated the PR with a link to the issue |
Yes, please 👀 |
@arkodg looks good to me. So on Docker Desktop we would add |
daemon/container_operations.go
Outdated
} | ||
if len(gateway) > 0 { | ||
sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(network.DockerHostInternalDNSName, gateway)) | ||
sboxOptions = append(sboxOptions, libnetwork.OptionExtraHost(network.DockerGatewayInternalDNSName, gateway)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the container is running with the default (bridge) network, does libnetwork.OptionExtraHost
also add entries to /etc/hosts
? (i.o.w. does this also use when not connected to a custom network (because the default bridge network doesn't currently use the embedded DNS)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually; I see you mention the reverse;
This PR allows containers to connect to Linux hosts by setting a Daemon flag called dns-resolve-docker-host which adds a host.docker.internal entry in /etc/hosts and maps it to docker0's IP
/etc/hosts
is only used on the default (bridge) network, but isn't used for DNS resolution on other networks (well, I guess it's used, but it would be different from resolution of other entries we set in the embedded DNS)?
edit: hm.. so we actually do use it for the custom hosts (--add-host
), so this would be consistent. Would it be better to use the embedded DNS?
docker network create foo
docker run --rm --network=foo --add-host foo.example.com:123.123.123.1 busybox cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
123.123.123.1 foo.example.com
172.19.0.2 de9b9822b00f
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens if this is, for example, a macvlan interface? Wouldn't the gateway be different (ie. not necessarily the "host" ip) in such a case?
cmd/dockerd/config.go
Outdated
@@ -64,6 +64,7 @@ func installCommonConfigFlags(conf *config.Config, flags *pflag.FlagSet) error { | |||
flags.Var(opts.NewListOptsRef(&conf.DNS, opts.ValidateIPAddress), "dns", "DNS server to use") | |||
flags.Var(opts.NewNamedListOptsRef("dns-opts", &conf.DNSOptions, nil), "dns-opt", "DNS options to use") | |||
flags.Var(opts.NewListOptsRef(&conf.DNSSearch, opts.ValidateDNSSearch), "dns-search", "DNS search domains to use") | |||
flags.BoolVar(&conf.DNSResolveDockerHost, "dns-resolve-docker-host", true, "dockerd will resolve the host.docker.internal DNS name if set to true") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a big fan of making this a boolean. Perhaps we could make this flag (that can be specified multiple times) to add custom entries to the resolver (either the embedded DNS or (see my other comment) entries in /etc/hosts
, depending on the situation).
For this particular case, we may need a "special" value for the gateway address (which I think is dynamically set), so that users can (haven't thought of the name of the flag yet);
--custom-dns-entry host.docker.internal=gateway \
--custom-dns-entry gateway.docker.internal=gateway
or, e.g. (same naming for the flag as for docker run
);
--add-host host.docker.internal=gateway \
--add-host gateway.docker.internal=gateway
With that (perhaps) Docker Desktop could also use that option?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would also make it compatible using Compose's extra_hosts:
field.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that option is per container/service, not at the daemon level
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@thaJeztah for this case, the community prefers some automagic
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also if we use embedded DNS it won't support this DNS name for containers attached to the default bridge
/docker0
network
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@thaJeztah for this case, the community prefers some automagic
While I understand that some magic could be nice to have, I think the reason we originally didn't add it on Linux was specifically because hard-coding could cause issues in some situations;
For reference, the host.docker.internal
was added on Docker Desktop to get parity with Linux (see #22753: "No docker0 on docker for mac?").
Related discussions use-cases / issues were
- Document how to connect to Docker host from container #1143 Document how to connect to Docker host from container
- Add dockerhost as an entry in /etc/hosts in all containers #23177 Add dockerhost as an entry in /etc/hosts in all containers
- (slightly related) Document how to get real remote client ip for service running in container #15086 "Document how to get real remote client ip for service running in container"
I think that;
- For the first issue; on Docker Desktop, docker has (almost) full control over how networking is set-up, so implementing
host.docker.internal
could be done because of that, whereas on Linux, networking configuration can widely differ, so hard-coding values may cause issues in some setups - For the other issues, expectations "how to connect to the host" widely varied;
- some people were looking at connecting to a (non-containerised) service running on the same host
- some people were looking at "how to connect to a service running on the same host" (either containerised or non-containerised) on a "interface", and how to get that IP-address?
- "public interface" / IP-address is ambiguous in setups where the docker host is behind a proxy (and the docker host itself does not know the public address
To get "magic", docker could still decide to set these options in the default configuration (systemd unit?), but hard-coding could potentially (see above) limit the usefulness if users cannot customise these settings, and if the hard-coded values don't work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@thaJeztah the hard coding can always be removed by setting dns-resolve-docker-host=false
if someone wants to be change this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But for the situations mentioned above, there would be no way to change host.docker.internal=<hard-coded-ip>
to host.docker.internal=<correct IP>
to be included in all containers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dns-resolve-docker-host=false
(In Daemon config) && --add-host host.docker.internal=<some-IP>
would address your concern
There is no ideal answer (I have raised the same questions), but apparently many developers want parity across OSs with the same Compose file and this PR attempts to do that
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it would have to be set on every container, every service, so not the same as this feature implements
Seeing some failures; s390x and powerpc integration tests (looks legit); https://ci.docker.com/public/job/moby/job/PR-40007/1/execution/node/217/log/
amd64 integration-cli tests: https://ci.docker.com/public/job/moby/job/PR-40007/1/execution/node/196/log/
Looks like there's a NPE:
|
4d494b6
to
ac434cd
Compare
CI failed due to #39966 (comment) |
ac434cd
to
2c34caf
Compare
There seems to be a fair number of edge cases this has a lot more edge cases than are accounted for here. In Docker4Mac there is a very specific and controlled network stack to get at the "host" IP. |
@cpuguy83 the above PR attempts to route |
61b4e98
to
d6e00a9
Compare
Ok, SGTM. |
This should be on For swarmkit consideraitons: this would be opaque to the managers and they would pass it down to workers and each worker would resolve it to its own IP. |
Here's a conclusion of my IRL talk with @arkodg:
Suggested implementation:
As someone pointed it out, this would work automatically with compose using the |
I think in addition to the above, we could add a configuration on the CLI that allows setting these as a default, similar to what we did with proxy configuration; docker/cli#93 |
@tibor Because in Will also not break older versions of Desktop WDYT @djs55 |
@arkodg Almost: there is no conditional logic for getting the gateway IP: it's always from the |
This sounds reasonable to me. Adding an extra argument to |
d6e00a9
to
dd6d54b
Compare
Why do I have to use an extra flag on linux while it works out of the box on windows and mac?! Just adding this record to every container by default would make much more sense. Inconsistencies over inconsistencies... |
The On Docker Desktop, the |
This doesn't seem to actually be documented in the official docs. |
@aradalvand You're right; I see I added a |
It doesn't work even though I have added the |
Other issues (linking for discoverability)
- What I did
This PR allows containers to connect to Linux hosts
by appending a special string "host-gateway" to --add-host
e.g. "--add-host=host.docker.internal:host-gateway" which adds
host.docker.internal DNS entry in /etc/hosts and maps it to host-gateway-ip
This PR also add a daemon flag call host-gateway-ip which defaults to
the default bridge IP
Docker Desktop will need to set this field to the Host Proxy IP
so DNS requests for host.docker.internal can be routed to VPNkit
- How to verify it