Docker Tip - How to use the host's IP Address inside a Docker container on macOS, Windows, and Linux
Tags: docker
Published: 2020-05-21 08:46:06

Once in a while, you may need your Docker host's IP address. For instance, you need to be able to connect to the host network from inside a Docker container to access your app or database running locally on the host. Debugging or reverse proxies running on your host are two additional example use-cases.

I'll show you how to easily make this work simultaneously for macOS, Windows, and Linux - because their docker networking settings differ.

## Docker Networking on macOS and Windows vs. Linux

For macOS and Windows the following special DNS name can be used:

> 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/Windows.
>
>The gateway is also reachable as `gateway.docker.internal`.
>
> _Source: https://docs.docker.com/docker-for-mac/networking/#use-cases-and-workarounds_
> _Source: https://docs.docker.com/docker-for-windows/networking/#use-cases-and-workarounds_

On Docker for Linux, the IP address of the gateway between the Docker host and the bridge network is `172.17.0.1` if you are using default networking.

Do you see the problem already? They are different, so you cannot simply run `docker-compose up -d` and _all_ operating systems behave the same. But I got you covered, there's an easy approach to make this work.

## Setup docker-compose

I've seen some suggestions, like creating a Linux-specific config file `docker-compose.override.yml` ([docs](https://docs.docker.com/compose/extends/)), but the solution a co-worker of mine came up with seems more elegant and less complex to me.

```yml
# docker-compose.yml
version: '3.7'

services:
  app:
    image: your-app:latest
    ports:
      - "8080:8080"
    environment:
      DB_UPSTREAM: http://${DOCKER_GATEWAY_HOST:-host.docker.internal}:3000
```

So, what is happening here? The `DB_UPSTREAM` should point to the host's IP and port 3000. `${DOCKER_GATEWAY_HOST:-host.docker.internal}` is the critical piece here. This expression tells docker-compose to either us the environment variable `DOCKER_GATEWAY_HOST` or use the fallback `host.docker.internal` when resolving this value.

On both macOS and Windows it works out of the box now without anything left to do. 🚀

If you are running this stack on Linux you need to have the `DOCKER_GATEWAY_HOST` environment variable set for the Docker gateway host. Simply put this line into your `.bashrc` (`.bash_profile` or `.zshrc`):

```
export DOCKER_GATEWAY_HOST=172.17.0.1
```

Now you can start the stack from macOS, Windows, and Linux without further configuration or overwrites. If you stick to this pattern - as [we](https://www.lovelysystems.com/?utm_medium=natterstefan&utm_source=devto) do - this works for every project of your company.

Great, isn't it? I hope this saves you some time!

## References

- [compose-file#extra_hosts](https://docs.docker.com/compose/compose-file/#extra_hosts): an entry with the ip address and hostname is created in `/etc/hosts` inside containers at build-time.

---

\>> Let's connect on Twitter 🐦: https://twitter.com/natterstefan <<