1

I have a Docker Compose v2 file which starts a container. I locally run a service on port 3001. I want to reach this service from the Docker container.

The Docker Compose file looks like this:

version: '2'
services:
  my-thingy:
    image: my-image:latest
    #network_mode: host #DOES not help
    environment:
      - THE_HOST_I_WANT_TO_CONNECT_TO=http://127.0.0.1:3001
    ports:
  - "3010:3010"

Now, how can I reach THE_HOST_I_WANT_TO_CONNECT_TO?

What I tried is:

  • Setting network_mode to host. This did not work. 127.0.0.1 could not be reached.
  • I can also see that I can reach the host from the container if I use the local IP of the host. A quick hack would be to use something like ifconfig | grep broadcast | awk '{print $2}' to obtain the IP and substitute that in Docker Compose. Since this IP can change on reconnect and different setups can have different ifconfig results, I am looking for a better solution.
user2609980
  • 10,264
  • 15
  • 74
  • 143

2 Answers2

2

This is a known issue with Docker Compose: see Document how to connect to Docker host from container #1143. The suggested solution of a dockerhost entry in /etc/hosts is not implemented.

I went for the solution with a shell variable as also suggested in a comment by amcdl on the issue:

Create a LOCAL_XX_HOST variable: export LOCAL_XX_HOST="http://$(ifconfig en0 inet | grep "inet " | awk -F'[: ]+' '{ print $2 }'):3001".

Then, for example, refer to this variable in docker-compose like this:

my-thingy:
    image: my-image:latest
    environment:
      - THE_HOST_I_WANT_TO_CONNECT_TO=${LOCAL_XX_HOST}
user2609980
  • 10,264
  • 15
  • 74
  • 143
  • I used it in virtualbox + debian duster, so I had to modify it a little as `"http://$(/sbin/ifconfig enp0s3 | grep "inet " | awk -F'[: ]+' '{ print $3 }'):3001"` – Aman Jun 16 '21 at 18:35
2

I've used another hack/workarkound from comments in the docker issue #1143. Seems to Work For Me™ for the time being... Specifically, I've added the following lines in my Dockerfile:

# - net-tools contains netstat, used to discover IP of Docker host server.
#   NOTE: the netstat trick is to make Docker host server accessible
#   from inside Docker container under name 'dockerhost'. Unfortunately,
#   as of 2016.10, there's no official/robust way to do this when Docker host
#   has no public IP/DNS entry. What is used here is built based on:
#   - https://github.com/docker/docker/issues/1143#issuecomment-39364200
#   - https://github.com/docker/docker/issues/1143#issuecomment-46105218
#   See also:
#   - http://stackoverflow.com/q/38936738/98528
#   - https://github.com/docker/docker/issues/8395#issuecomment-200808798
#   - https://github.com/docker/docker/issues/23177
RUN apt-get update && apt-get install -y net-tools
CMD (netstat -nr | grep '^0\.0\.0\.0' | awk '{print $2" dockerhost"}' >> /etc/hosts) && \
        ...old CMD...

With this, I can use dockerhost as the name of the host where Docker is installed. As mentioned above, this is based on:

  • https://github.com/docker/docker/issues/1143#issuecomment-39364200

    (...) One way is to rely on the fact that the Docker host is reachable through the address of the Docker bridge, which happens to be the default gateway for the container. In other words, a clever parsing of ip route ls | grep ^default might be all you need in that case. Of course, it relies on an implementation detail (the default gateway happens to be an IP address of the Docker host) which might change in the future. (...)

  • https://github.com/docker/docker/issues/1143#issuecomment-46105218

    (...) A lot of people like us are looking for a little tidbit like this

    netstat -nr | grep '^0\.0\.0\.0' | awk '{print $2}'
    

where netstat -nr means:

Netstat prints information about the Linux networking subsystem.
(...)
--route , -r
Display the kernel routing tables.
(...)
--numeric , -n
Show numerical addresses instead of trying to determine symbolic host, port or user names.

akavel
  • 4,789
  • 1
  • 35
  • 66