docker / for-linux

Docker Engine for Linux
https://docs.docker.com/engine/installation/
751 stars 84 forks source link

Support host.docker.internal DNS name to host #264

Closed Mahoney closed 2 years ago

Mahoney commented 6 years ago

Expected behavior

As in docker-for-mac and docker-for-windows, inside a container, the DNS name host.docker.internal resolves to an IP address allowing network access to the host (roughly the output of ip -4 route list match 0/0 | cut -d' ' -f3 inside the same container).

Actual behavior

host.docker.internal resolves to nothing

Steps to reproduce the behavior

Execute docker run --rm alpine nslookup host.docker.internal

See it returns nslookup: can't resolve 'host.docker.internal': Name does not resolve

Output of docker version:

Client:
 Version:   18.03.0-ce
 API version:   1.37
 Go version:    go1.9.4
 Git commit:    0520e24
 Built: Wed Mar 21 23:10:09 2018
 OS/Arch:   linux/amd64
 Experimental:  false
 Orchestrator:  swarm

Server:
 Engine:
  Version:  18.03.0-ce
  API version:  1.37 (minimum version 1.12)
  Go version:   go1.9.4
  Git commit:   0520e24
  Built:    Wed Mar 21 23:08:36 2018
  OS/Arch:  linux/amd64
  Experimental: false

Output of docker info:

Containers: 0
 Running: 0
 Paused: 0
 Stopped: 0
Images: 1
Server Version: 18.03.0-ce
Storage Driver: overlay2
 Backing Filesystem: extfs
 Supports d_type: true
 Native Overlay Diff: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
 Volume: local
 Network: bridge host macvlan null overlay
 Log: awslogs fluentd gcplogs gelf journald json-file logentries splunk syslog
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: cfd04396dc68220d1cecbe686a6cc3aa5ce3667c
runc version: 4fc53a81fb7c994640722ac585fa9ca548971871
init version: 949e6fa
Security Options:
 apparmor
 seccomp
  Profile: default
Kernel Version: 4.13.0-37-generic
Operating System: Ubuntu 17.10
OSType: linux
Architecture: x86_64
CPUs: 1
Total Memory: 1.947GiB
Name: rob-VirtualBox
ID: 3L2C:BTV3:TQO2:4SAG:XVW5:744G:MPWQ:62FK:56DP:KH3Z:EQ7Z:TBR5
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
 127.0.0.0/8
Live Restore Enabled: false

WARNING: No swap limit support

Additional environment details (AWS, VirtualBox, physical, etc.)

Running Ubuntu in VirtualBox 5.2.8 on OS/X 10.13.4

bscheshirwork commented 6 years ago

same situation. I want to use this in docker-compose.yml for replace remote_host

    environment:
      XDEBUG_CONFIG: "remote_host=192.168.0.83 remote_port=9001 var_display_max_data=1024 var_display_max_depth=5"
$ docker-compose -f ~/projects/docker-yii2-app-advanced/docker-run/docker-compose.yml run --rm --entrypoint nslookup php "host.docker.internal"
Creating network "dockerrun_default" with the default driver
Creating dockerrun_mysql_1 ... done
Creating dockerrun_db_1    ... done
nslookup: can't resolve '(null)': Name does not resolve

nslookup: can't resolve 'host.docker.internal': Name does not resolve
...
Kernel Version: 4.4.0-116-generic
Operating System: Ubuntu 16.04.4 LTS
bscheshirwork commented 6 years ago

https://docs.docker.com/docker-for-mac/networking/#use-cases-and-workarounds

I want to connect from a container to a service on the host

The host has a changing IP address (or none if you have no network access). From 18.03 onwards our recommendation is to connect to the special DNS name host.docker.internal, which resolves to the internal IP address used by the host.

The gateway is also reachable as gateway.docker.internal.

JuxhinDB commented 6 years ago

Same situation, when taking a closer look at /etc/hosts I notice the following:

172.17.0.2 f85e063d8c3e

Which suggests that it's just setting it to a random ID rather than host.docker.internal which is what I need.

Zomis commented 6 years ago

When I tried to find out how to connect to host from Docker I found this question/answer on Stack Overflow: https://stackoverflow.com/a/43541732/1310566

I was not aware at the time that it only applied to macOS and Windows (it was just recently edited)

atolia commented 6 years ago

While this feature not on linux I use

web:
  image: httpd:2.4
  volumes:
    - ......
  entrypoint: 
  - /bin/sh
  - -c 
  - ip -4 route list match 0/0 | awk '{print $$3" host.docker.internal"}' >> /etc/hosts && httpd-foreground 
bscheshirwork commented 6 years ago

@atolia This look like work with docker-compose exec web and don't work with docker-compose run --rm --entrypoint /bin/bash web

hernandev commented 6 years ago

Mimic on that can be done with:

echo -e "`/sbin/ip route|awk '/default/ { print $3 }'`\tdocker.host.internal" | sudo tee -a /etc/hosts > /dev/null

Notice @atolia already provided a similar solution, but he is not considering non-privileged default USER, this one will work for non-root images with passwordless sudo available, for images where default user is root, just remove the sudo part.

This command will make docker.host.internal available regardless of the Docker version OR execution mode. I'm using this on entrypoint files.

acuthbert commented 6 years ago

Firstly - docker is an amazing tool and so thank you for all who work tirelessly on it! As a leader of a large mixed team of linux and mac engineers this has been one of the biggest "why did we leave vagrant" questions I get hammered about when we called time on vagrant. It is very frustrating that this exists on mac and windows and not linux. We need connect back for xdebug and for letting selenium running in a container to access local urls for acceptance testing. This difference is bloating our build scripts with more and more fragility so it would be great if this was standardised. Is it not a worry if the same version of docker engineer on the 3 platforms can deviate in feature set?

FX-HAO commented 6 years ago

docker.host.internal is still unavailable on my mac. And I can't connect to my host with 172.17.0.1. My docker version:

Client:
 Version:      18.03.1-ce
 API version:  1.37
 Go version:   go1.9.5
 Git commit:   9ee9f40
 Built:        Thu Apr 26 07:13:02 2018
 OS/Arch:      darwin/amd64
 Experimental: false
 Orchestrator: swarm

Server:
 Engine:
  Version:      18.03.1-ce
  API version:  1.37 (minimum version 1.12)
  Go version:   go1.9.5
  Git commit:   9ee9f40
  Built:        Thu Apr 26 07:22:38 2018
  OS/Arch:      linux/amd64
  Experimental: true
chaospixel commented 6 years ago

In case you missed it: docker.for.mac.host.internal and docker.for.mac.localhost do work - but only on docker for mac...

FX-HAO commented 6 years ago

From 18.03 onwards our recommendation is to connect to the special DNS name host.docker.internal

Older aliases are deprecated in favor of this one. And I tried them, not working.

mnd999 commented 6 years ago

Not working here either (unsurprisingly).

mnd999 commented 6 years ago

@JuxhinDB it's not a random number, it's the container id. Still not useful though.

jcoutch commented 6 years ago

I'm running a microsoft/dotnet-framework container on a Windows host (v18.03.1-cd-win65 17513), and host.docker.internal does not work.

kunal-bhatia commented 6 years ago

Any idea, when will linux support for connecting to special DNS will be fixed?

bscheshirwork commented 6 years ago

@kunalbhatia87 wait 4 resolve this issue? :laughing:

rfay commented 6 years ago

There are several comments (and workarounds) here that mistakenly use "docker.host.internal", which I don't think was ever supported. The hostname we want to be supported is the one that's supported in Docker for Windows and Docker for Mac, "host.docker.internal"

rfay commented 6 years ago

@Mahoney I think you should check "This is a bug report" in the OP. This is a bug. Docker team, please acknowledge it, thanks!

Mahoney commented 6 years ago

@rfay I'm not aware of this ever being a documented feature of Linux docker - as far as I can see it's only documented for docker-for-mac and docker-for-windows, and only as a recent change in each case. I couldn't find any discussion around the choice or anything to suggest it had been agreed as something all versions of Docker should implement, though it would make sense to me if it were.

So as far as I can see "feature request" rather than "bug" is the correct categorisation.

brunosaboia commented 6 years ago

@Mahoney while I do agree that this is a feature request, it's an important one. In the end, you want your dev team to use a shared config file all across — the underlying OS should be indifferent.

For me, running Linux on a Mac-based team, it's very bad to have to either create and ignore the changes to a config file, or to have to create hosts entries in each VM to mimic Docker for Mac behavior. I think it's simpler to just have an additional entry on the Docker networking so that the host is always reachable using the same hostname.

jtreminio commented 6 years ago

@brunosaboia What I do while waiting for this to be resolved is create Linux-specific config files and mount them via docker-compose.override.yml.

Not the perfect workaround, but it is the best solution right now.

mrpink76 commented 6 years ago

I'm running a windows container on a windows host: microsoft/dotnet:2.1-aspnetcore-runtime-nanoserver-1709

host.docker.internal does not work to connect to a service on the host.

Mahoney commented 6 years ago

Issues with docker for windows should be raised in the docker/for-win repo after an appropriate search such as https://github.com/docker/for-win/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+host.docker.internal

atrauzzi commented 6 years ago

Yeah, this definitely needs to be implemented so that we can have consistency.

Really, containers should always have had something like this anyway.

mastilver commented 6 years ago

As a workaround, you can follow: https://dev.to/bufferings/access-host-from-a-docker-container-4099

Working fine for me

atrauzzi commented 6 years ago

Sadly, I'm not going to take on the debt and overhead of an entrypoint script in all of my containers.

Definitely wouldn't want this "workaround" to become a permanent solution.

perlun commented 6 years ago

@FX-HAO If you have the same problem as me, try disabling custom DNS settings in here:

image

(It was defunct on my machine also, but removing the custom DNS settings made host.docker.internal work as intended.)

Note: This is not related to the OP:s question, so sorry for wandering off-topic a bit here.

FX-HAO commented 6 years ago

@perlun Fix my problem, Thanks.

nasatome commented 6 years ago

This works for me in alpine, ubuntu and debian images in linux host:

    if grep "docker.host.internal" /etc/hosts; \
    then \
    echo -e "\n it already exists" ;\
    else \
    echo -e "`/sbin/ip route|awk '/default/ { print $3 }'`\tdocker.host.internal" >> /etc/hosts ;\
    fi
atrauzzi commented 6 years ago

That's just a variation of an entrypoint script, as mentioned already. That's not a solution or relevant to this issue.

The idea here is that we need a uniform hostname to use on linux, docker for mac and docker for windows.

loicortola commented 6 years ago

+1 on this, for consistency!

mdelapenya commented 6 years ago

The problem disappeared after removing the DNS section in my daemon config

Thanks!

atrauzzi commented 6 years ago

@mdelapenya - Best to qualify that your comment is off topic for this ticket. The issue referenced by the original description is not resolved.

mdelapenya commented 6 years ago

Thanks @atrauzzi for your -1, but I suffered for this error and I just posted my workaround/solution.

I promise don't disturb you with my feedback 🔕

perlun commented 6 years ago

@seemethere @thaJeztah It would be interesting to hear your thoughts about this one. I would be willing to make an attempt at filing a PR about this, if you can point me in the right direction. (where is the Docker-internal DNS code retained, in what repo, and how can the new functionality be applied to Docker-for-Linux scenarios only?)

atrauzzi commented 6 years ago

@mdelapenya - Really, it's as simple as editing your comment to note that it's off topic. Wouldn't be so bad then. The risk is that your remark offers so little context, it makes this issue sound close-able to someone reading at a glance.

Don't think you have any reason to be sour, I'm happy to remove the -1 and delete my clarification if you edit yours! 😄

Be considerate of other people in the thread!

alexdashkov commented 6 years ago

@perlun Did you find a solution to make docker.host.internal works with the custom DNS settings?

thomasclaes commented 6 years ago

Also curious to know whether there will be one DNS entry to rule them all!

bscheshirwork commented 6 years ago

:smiley_cat: One ring to rule them all

JLangevine commented 6 years ago

hopping in here since I'm new to this and it's interesting. I'm so happy I found this thread.

perlun commented 6 years ago

@alexdashkov

@perlun Did you find a solution to make docker.host.internal works with the custom DNS settings?

Unfortunately, no. There was no pressing reason for me to use the custom DNS so I could just go with whatever my DHCP server would hand me.

(Again: this is the off-topic part of the thread. I will refrain from writing more about this; the underlying problem is that host.docker.internal does not work at all on Docker for Linux, unlike on Windows and macOS.)

Destroy666x commented 6 years ago

Too bad there's noone willing and/or knowing how to do such an important consistency change for such a long time. And actually the part that relates to the most popular system when it comes to Docker usage is the only one affected...

atrauzzi commented 6 years ago

Feel free to retweet, like and reply to this: https://twitter.com/Omega_/status/1024360453668003841

I agree, there just seems to be no triage/oversight here and this is a fairly high profile issue. Someone at a product level at docker surely would give this some priority.

GabLeRoux commented 6 years ago

Ok this is hard to see, but it's terrible. host.docker.internal is not available on Linux on Docker. It works on MacOS since 18.03.

Still have doubts? Try it:

docker run --rm -it bash:latest ping host.docker.internal

Issue description mentioned it works on Windows (I did not test that, but it's probably ok). I suppose it's safer to not have this on a production server for security reasons, but for debugging, it's especially useful for PHP XDebug.

Entrypoint fix for Docker on Linux

As shown in previous comments, here's what one can add to its entrypoint.sh (written in bash, I refactored https://github.com/docker/for-linux/issues/264#issuecomment-402575483 for readability).

#!/usr/bin/env bash
set -x
set -e

function fix_linux_internal_host() {
  DOCKER_INTERNAL_HOST="host.docker.internal"

  if ! grep $DOCKER_INTERNAL_HOST /etc/hosts > /dev/null ; then
    DOCKER_INTERNAL_IP=`/sbin/ip route | awk '/default/ { print $3 }' | awk '!seen[$0]++'`
    echo -e "$DOCKER_INTERNAL_IP\t$DOCKER_INTERNAL_HOST" | tee -a /etc/hosts > /dev/null
    echo "Added $DOCKER_INTERNAL_HOST to hosts /etc/hosts"
  fi
}

fix_linux_internal_host

# [...] some other things you may want in your entrypoint
# Make sure you use the same magic as the FROM php:whatever you are using such as:
# https://github.com/docker-library/php/blob/master/7.3-rc/stretch/apache/docker-php-entrypoint
# https://github.com/docker-library/php/blob/master/7.3-rc/stretch/cli/docker-php-entrypoint
exec "$@"

Edit 1: Updated to match @brunosaboia's comment Edit 2: Added shebang, required entrypoint exec command and notes Edit 3: Add example to show that host.docker.internal is not available on Linux

There are two comments describing how to fix this with the entrypoint so far:

Please note that they broke the hostname 🔥. Right value is

:heavy_check_mark: It's spelled ok in above fix_linux_internal_host. This was very misleading.

Docker command line argument

Another way around (also mentioned in above comments) is to pass --add-host <some_hardcoded_ip> where one must first find its host ip exposed to container by running following command (inside the container):

/sbin/ip route|awk '/default/ { print $3 }'
brunosaboia commented 6 years ago

@GabLeRoux , thanks for that.

I would change your ip route call to the following:

/sbin/ip route | awk '/default/ { print $3 }' | awk '!seen[$0]++'

Just to be sure you're removing duplicates, if any.

nyetwurk commented 6 years ago

Why can't this be an option similar to --link?

https://docs.docker.com/v17.09/engine/userguide/networking/default_network/configure-dns/

atrauzzi commented 6 years ago

Because it has to be automatic.

nyetwurk commented 6 years ago

Sorry, I meant it could take a similar approach by making sure dnsmasq's hostfile gets updated and dnsmasq gets restarted accordingly, whenever a docker bridged network comes up or goes down.

rigolepe commented 6 years ago

Using host.docker.internal in the extra_hosts config doesn't seem to work either:

services:
  apigateway:
    image: apigateway-img
    container_name: apigateway
    ports:
     - 80:80
    extra_hosts:
     - wdb:host.docker.internal

Running docker-compose gives:

ERROR: for apigateway  Cannot create container for service apigateway: b'invalid IP address in add-host: "host.docker.internal"'

Running this on Docker for Mac version:

Docker version 18.06.0-ce, build 0ffa825
docker-compose version 1.22.0, build f46880f

I tried docker.for.mac.host.internal as well, but it gives the same issue.

However, if I start a container manually and perform a ping to host.docker.internal, I get a connection:

root@f7bbd5f4702d:/# ping host.docker.internal
PING host.docker.internal (192.168.65.2) 56(84) bytes of data.
64 bytes from 192.168.65.2 (192.168.65.2): icmp_seq=1 ttl=37 time=0.881 ms
64 bytes from 192.168.65.2 (192.168.65.2): icmp_seq=2 ttl=37 time=0.543 ms
64 bytes from 192.168.65.2 (192.168.65.2): icmp_seq=3 ttl=37 time=0.330 ms
64 bytes from 192.168.65.2 (192.168.65.2): icmp_seq=4 ttl=37 time=0.300 ms
^C
--- host.docker.internal ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3076ms
rtt min/avg/max/mdev = 0.300/0.513/0.881/0.233 ms

It seems like host.docker.internal cannot be resolved during docker-compose setup and then it fails that container. To me, it seems like it would be logical that DNS names in the extra_hosts config are passed through as such without lookup attempt during docker-compose setup time?

pscheit commented 6 years ago

@rigolepe you cannot use a non numeric ip address in "extra_hosts"