As the title says. I need to be able to retrieve the IP address the docker hosts and the portmaps from the host to the container, and doing that inside of the container.
AFAIK, in the case of Docker for Linux (standard distribution), the IP address of the host will always be 172.17.0.1
(on the main network of docker, see comments to learn more).
The easiest way to get it is via ifconfig
(interface docker0) from the host:
ifconfig
From inside a docker, the following command from a docker: ip -4 route show default | cut -d" " -f3
You can run it quickly in a docker with the following command line:
# 1. Run an ubuntu docker
# 2. Updates dependencies (quietly)
# 3. Install ip package (quietly)
# 4. Shows (nicely) the ip of the host
# 5. Removes the docker (thanks to `--rm` arg)
docker run -it --rm ubuntu:19.10 bash -c "apt-get update && apt-get install iproute2 -y && ip -4 route show default | cut -d' ' -f3"
The standard best practice for most apps looking to do this automatically is: you don't. Instead you have the person running the container inject an external hostname/ip address as configuration, e.g. as an environment variable or config file. Allowing the user to inject this gives you the most portable design.
Why would this be so difficult? Because containers will, by design, isolate the application from the host environment. The network is namespaced to just that container by default, and details of the host are protected from the process running inside the container which may not be fully trusted.
There are different options depending on your specific situation:
If your container is running with host networking, then you can look at the routing table on the host directly to see the default route out. From this question the following works for me e.g.:
ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p'
An example showing this with host networking in a container looks like:
docker run --rm --net host busybox /bin/sh -c \
"ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p'"
For some versions of Docker Desktop, they injected a DNS entry into the embedded VM:
getent hosts host.docker.internal | awk '{print $1}'
If you are running in a cloud environment, you can check the metadata service from the cloud provider, e.g. the AWS one:
curl http://169.254.169.254/latest/meta-data/local-ipv4
If you want your external/internet address, you can query a remote service like:
curl ifconfig.co
Each of these have limitations and only work in specific scenarios. The most portable option is still to run your container with the IP address injected as a configuration, e.g. here's an option running the earlier ip
command on the host and injecting it as an environment variable:
export HOST_IP=$(ip route get 1 | sed -n 's/^.*src \([0-9.]*\) .*$/\1/p')
docker run --rm -e HOST_IP busybox printenv HOST_IP
docker run -it --rm alpine nslookup host.docker.internal
... prints the host's IP address ...
nslookup: can't resolve '(null)': Name does not resolve
Name: host.docker.internal
Address 1: 192.168.65.2
On Mac and Windows, you can use the special DNS name host.docker.internal
.
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. This is for development purpose and will not work in a production environment outside of Docker Desktop for Mac.
In linux you can run
HOST_IP=`hostname -I | awk '{print $1}'`
In macOS your host machine is not the Docker host. Docker will install it's host OS in VirtualBox.
HOST_IP=`docker run busybox ping -c 1 docker.for.mac.localhost | awk 'FNR==2 {print $4}' | sed s'/.$//'`
With https://docs.docker.com/machine/install-machine/
a) $ docker-machine ip
b) Get the IP address of one or more machines.
$ docker-machine ip host_name
$ docker-machine ip host_name1 host_name2
I have Ubuntu 16.03. For me
docker run --add-host dockerhost:`/sbin/ip route|awk '/default/ { print $3}'` [image]
does NOT work (wrong ip was generating)
My working solution was that:
docker run --add-host dockerhost:`docker network inspect --format='{{range .IPAM.Config}}{{.Gateway}}{{end}}' bridge` [image]