I’m using Docker since around Oktober 2017. Since I started using it I’m constantly searching for a way to get access to the host via the host’s IP address.
I want a solution without any dependencies. This means using as less as possible extra software. The goal is not to rely on tools or scripts other than Docker.
It doesn’t matter what you do with Docker Network, it’s always a mess.
For a better understanding, I also use Host as a synonym for the host machine, where the Docker daemon is running. And Container for what’s running inside Docker.
Host LAN IP address
This would be the easiest way to access the host: using the host’s LAN IP address inside the container. But I would not use it as the host’s IP address may be assigned dynamically. This is perfect for test cases, but not acceptable as a long-term solution or production.
Also on root-servers with static IP addresses this solution is not very reliable. Consider moving the container to another host machine. You don’t want to change the IP address on multiple locations.
Host Loopback Interface Alias
The loopback interface is also sometimes called localhost, or 127.0.0.1
.
You can set an alias on the host’s loopback interface. Then using this alias IP address inside the container to access the host. You cannot use 127.0.0.1
inside the container. This would point inside the container.
Using an alias works well. The problem is when you are working in a team. Every developer has to setup the exact same alias. On each working machine.
To set 10.254.254.254
as an alias under macOS use the following command:
$ sudo ifconfig lo0 alias 10.254.254.254
Create your own hostname
Creating your own hostname and using it through all projects is one of the best solutions. Especially when the container has to access the host machine, go for this. Like all other solutions, it requires work to do on the host machine. I would rather do nothing at all on the host system, but sadly, this is how Docker is designed. You have to adapt and prepare stuff on the host system. In most use cases it’s normal to prepare the host as well.
Even more work, when you have different host systems running. But let’s focus only on Debian Linux. The following shell commands have to be executed before the image will be started. So, creating a separate run_docker.sh
script here, to prepare everthing, is a good decision.
This command returns the default network interface of the host system.
$ route -4 | awk '/^default/ { print $8 }'
Or more advanced for Bash scripts:
default_if=$(route -4 | awk '/^default/ { print $8 }')
Next, get the IP address for the default network interface.
host_ip=$(ifconfig "${default_if}" | awk '/inet / { print $2 }' | head -1)
When starting the image, use $host_ip
to set host.docker.local
. This will add a new entry to /etc/hosts
inside the container.
docker run \
--add-host="host.docker.local:$host_ip" \
...
You can use host.docker.local
as a hardcoded hostname in configurations to access the host machine. Do not use .localhost
as top-level domain (TLD) here since some DNS servers have a *.localhost
catch-all rule which resolves to 127.0.0.1
. Which is senseless in this case.
You are more independent when you already know forefront that the data on the host and the Docker container will always be on the same machine. Even if you move both together you don’t have to change anything in regarding of hostnames because host.docker.local
will always point to the host machine.
Use DNS
The most Docker container I’m working with have to access a MySQL database. The databases are always outside of Docker. And they never ever will. (It’s the worst idea ever, having a database inside Docker.)
When you have such a container it’s better to use DNS. Even if the database is on the same machine as the Docker container, I would not go with the previous (Create your own hostname) solution. Just add the hostname to your DNS server and use it in the configurations inside the container. For example, db.your-company.tld
will do the job well. It’s more comfortable using a fixed DNS hostname when moving the container to another host machine. At least you have one thing less to change.
Don’t underestimate this. It’s still a shitload of work manually moving a container from one host to another. So being as host independent as possible should be always your intention.
Docker for Mac
From StackOverflow:
On Docker for Mac, as of version 18.03, you can use
host.docker.internal
as the host’s IP. […] This is an update fromdocker.for.mac.localhost
, available since version 17.06, anddocker.for.mac.host.internal
, available since version 17.12, which may also still work.
This is actually very stupid. I want to use the same hostname regardless on which host system I run the container. This is the whole point of Docker, right? To be independent.
As I said above, you always have work to do on the host system. Let’s escalate a bit. I was introduced to Docker like Build it once, run it everywhere. Do not get fooled by that. This is delusional, since you always have to configure the host system somehow.
So, docker.for.mac.localhost
is useless since in most cases you don’t have a Linux- or Mac-only environment in your company. It’s mixed. You have developers using Linux and Mac and Windows. This hostname makes no sense since in 99.99 % it’s a mixed Host OS environment. I don’t develop a container under macOS and deploy it to a macOS server. I deploy it to Linux. This is how everyone does. At least in my sphere. What’s even the whole point of docker.for.mac.localhost
? Only a development utility? I cannot even use it on all dev machines. Don’t use it at all.
Conclusion
The best solution would be to use an alias (like host.docker.internal
as in Docker for Mac) provided by Docker as a build-in functionality, for all host systems. Regardless which host system the container is running on. Sadly, this is not a build-in feature of Docker. As long as Docker is not providing such a feature out-of-the-box we have to use our own solution to be host independent. You can see in the solutions above, it’s about which data you want to access from inside the container.
As I said before, being as host independent as possible should be always your intention when dealing with Docker.