How to connect to the Docker host from inside a Docker container?
As of Docker version
18.03, you can use the
host.docker.internal hostname to connect to your Docker host from inside a Docker container.
This works fine on Docker for Mac and Docker for Windows, but unfortunately, this is not was not supported on Linux until Docker
20.10.0was released in December 2020.
Starting from version
20.10 , the Docker Engine now also supports communicating with the Docker host via
host.docker.internal on Linux. Unfortunately, this won't work out of the box on Linux because you need to add the extra
— add-hostrun flag:
This blog post demonstrates the issue on Linux using a simple example and also explains the configuration to make sure you have an identical behavior across Linux, Mac, and Windows.
From the Docker documentation for MacOS and Windows:
The host has a changing IP address (or none if you have no network access). We recommend that you connect to the special DNS name
host.docker.internalwhich 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 Windows / Mac.
You can also reach the gateway using
At the time of writing this blog post, the latest stable Docker version is:
Docker version 20.10.8, build 3967b7d
You need to have at least Docker version 20.10.0 installed to make this example work on Linux machines.
Why do I even want to reach my Docker host from inside a Docker container?
Before diving into the issue and solution, it’s good to understand a use case; why do I even need to reach the Docker host from inside my running Docker container?
I’m a Spring Boot developer and building a new feature into my application. For observability reasons, I add custom metrics to my code. The metrics are exposed via a Spring Boot actuator endpoint in a way Prometheus can read them. On top of the metrics, I would like to create Grafana dashboards.
For development purposes, I like to run Prometheus and Grafana in Docker while I’m developing my application in my favorite IDE, IntelliJ.
After I implemented my changes, I launch the application from my IDEA, and the application will start on my host.
In Docker, both Prometheus and Grafana are running. Before I can build some nice dashboards, Prometheus needs to scrape the metrics endpoint of my application and will continue to do so on a configured interval. Once again, the Spring Boot application is not running in Docker but on the host itself!
Prometheus is configured to reach the Spring Boot application running on the Docker host using the special DNS name:
To not bother you with a complete Grafana and Prometheus setup but still be able to show the default behavior on Linux, we will use the following setup:
- We run a simple Spring Boot application that exposes a REST endpoint returning a ‘Hello World’ message.
- We start a Ubuntu container in Docker and execute a REST call to the Spring Boot application running on the host OS(Linux) using curl.
You can clone the example from Github: https://github.com/j-tim/connect-docker-host-from-docker-container-example
- Make sure to have Java 11 installed
- Spring Boot CLI installed (make sure not to install version 3 or later, since the run command has been removed since 3.x)
- Docker installed
The Spring Boot Hello World application code (groovy) will:
- expose a REST endpoint
- start at port 8080
First, start the Spring Boot application using the Spring Boot CLI:
spring run helloWorld.groovy
Please note the run command has been removed from the CLI since version 3.x! Use the latest 2.7.x version of the Spring Boot CLI to make this example work.
Start an Ubuntu container:
docker run -it ubuntu bash
itis short for
- executing the command take you directly inside the container
- allows you to interact with
/bin/bashinside the container
- Long story short: you will have a
bashsession inside an Ubuntu Docker container
Inside the Ubuntu container, install curl:
apt update && apt install curl -y
Do a call to the Spring Boot application running on the host using
Because we didn’t start the container with the extra run flag, we will run into the following issue on Linux (on both Mac and Windows, it will just work fine):
root@8024db7c38fe:/# ping host.docker.internal
ping: host.docker.internal: Name or service not known
How to make it work?
On Linux, you can’t automatically resolve
host.docker.internal, you need to provide the following run flag when you start the container:
In the example of the Ubuntu container:
docker run -it --add-host=host.docker.internal:host-gateway ubuntu bash
When you repeat the steps again, you now can reach the Spring Boot application that is running on the host from inside the Ubuntu container:
root@c1d299ee554d:/# curl http://host.docker.internal:8080
Hello world container. You are able to reach the Docker host!
How about Docker compose?
Most of the time I use Docker compose to start my Docker containers. To get the same behavior, you need to specify the
host.docker.internal:host-gateway using the extra_hosts parameter.
Other special DNS names
gateway.docker.internalto reach the gateway
On Mac and Windows, it is possible to use:
- It’s easy to connect to the host OS from inside a Docker container
- Avoid the use of OS-specific DNS names flavors like:
- In Docker for Mac and Docker for Windows, you can connect to the host out of the box by using the special DNS name:
- For Linux, you need the magic string
host-gatewayto map to the gateway inside the container. This allows you to use the hostname
host.docker.internalto access the host from inside a container.
- To get a consistent behavior on all platforms (Mac, Windows, and Linux) use
host.docker.internal:host-gatewayin your Docker compose file.
- Play around yourself! Clone my Github repo.
Tap the 👏 button if you found this article useful!
Any questions or feedback?
Reach out to me on Twitter: @TimvanBaarsen