4

Question: (the short version)

When using Docker for application development, how do I configure a Docker-compose file to let me access the IP address of a server on the host network from inside the docker container? I don't want to access the host itself -- but instead want to access another server on the same network as the host. I also need to have various docker containers be able to talk to each other.

What is the cleanest way to allow access to host-network IPv4 resources from inside of a docker container and still allow inter-container communication?

All the background and details are below (aka the long version).


Setup:

I'm writing an application that polls a Modbus server to collect measured data at a given interval. The Modbus server is at 192.168.1.50 port 502 on my local network. I can successfully ping that server from my computer.

Here's my development approach:

  • application is inside a docker container
  • developing in a Mac environment
  • using Django-3.1/postgres to build the UI and store the data (for now)
  • using the pymodbus library to manage communication between the application and the remote Modbus server

Here's the Docker-compose file that creates the application environment:

version: '3.8'

services:

  db:
    container_name: db
    image: postgres:10.7
    environment:
      POSTGRES_PASSWORD: pwd
      POSTGRES_DB: app_db
    volumes:
      - ./data/postgres:/var/lib/postgresql/data
    ports:
      - 5432:5432

  web:
    container_name: web
    build:
      context: ../.
      dockerfile: ./_app/dev/Dockerfile
    volumes:
    - ../.:/app
    ports:
    - 8000:8000
    depends_on:
      - db
    env_file:
      - app.env
    command: ./manage.py runserver 0.0.0.0:8000

And here's the Dockerfile:

FROM python:3.8.5-buster

RUN mkdir /app
WORKDIR /app

RUN apt-get update -y
RUN apt-get install inetutils-traceroute -y

COPY ./_app/dev/python_reqs.txt /app/python_reqs.txt
RUN pip install --upgrade pip
RUN pip install -r python_reqs.txt

# Install wait-for-it
COPY ./_app/wait-for-it.sh /usr/local/bin/
RUN chmod u+x /usr/local/bin/wait-for-it.sh

# Configure custom entrypoint to wait for postgres and run webserver
COPY ./_app/dev/custom-entrypoint /usr/local/bin/
RUN chmod u+x /usr/local/bin/custom-entrypoint
ENTRYPOINT ["custom-entrypoint"]

EXPOSE 8000

Problem:

From inside the 'web' docker container I cannot access the Modbus server on the host LAN. I cannot ping its IP address (192.168.1.50).

traceroute 192.168.1.50 provides no useful info. It just fails.

When I run docker-compose up a docker network called '_app_default' is created. Here's what I get when I run docker network inspect _app_default:

[
    {
        "Name": "_app_default",
        "Id": "59f0836c2f3017c537f973a38ab3a55ad96e2ed737c4ac111fc0e911fa0c8a67",
        "Created": "2020-09-13T18:51:14.6395366Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "192.168.112.0/20",
                    "Gateway": "192.168.112.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": true,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "28af77ef2d6f99812cb392c8f9eca045b150256c464befc3bb249c9de9e653c1": {
                "Name": "db",
                "EndpointID": "d657f2f29699ada859447c919ad2c94195a6e9a7ae7eeb35989560d2717183c5",
                "MacAddress": "02:42:c0:a8:70:02",
                "IPv4Address": "192.168.112.2/20",
                "IPv6Address": ""
            },
            "a8a619d664a27286e276614e549514dff2c15c5c3c44c39e127fec54ec2b5c6b": {
                "Name": "web",
                "EndpointID": "8f1661c6fa24104a70171d1f830e1fe34ed8d89bacd55c9b9d05dc62f64112c0",
                "MacAddress": "02:42:c0:a8:70:03",
                "IPv4Address": "192.168.112.3/20",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {
            "com.docker.compose.network": "default",
            "com.docker.compose.project": "_app",
            "com.docker.compose.version": "1.27.0"
        }
    }
]

What I Already Tried:

I tried using network_mode: "host" in the 'web' service definition. That did not help.

I did my best to read through the Docker networking documentation but I can't find a straightforward solution to this situation and I get all turned around -- I'm unfortunately not good with networking topics -- yet :) . Do I need an 'overlay' network? Or a 'macvlan'? Help!

Any assistance that you StackOverflow superstars can send would be greatly appreciated. Thank you!!

-Allan

allan
  • 153
  • 2
  • 6
  • Just a note: by default, there is no restriction on outbound connections from Docker containers. They are free to connect to other hosts on your network and on the internet. If you're having problems, something isn't working as expected. – larsks Sep 13 '20 at 20:42
  • 1
    Thanks for your comment @larsks. Is it possible that I'm running into these known docker networking limitations? https://docs.docker.com/docker-for-mac/networking/#there-is-no-docker0-bridge-on-macos – allan Sep 14 '20 at 00:20

1 Answers1

2

It looks like you have overlapping ip ranges of docker network and local network. To solve this you need to override docker network address pool e.g.

edit docker daemon config

$ cat ~/.docker/daemon.json
{
  "debug" : true,
  "default-address-pools" : [
    {
      "base" : "172.31.0.0/16",
      "size" : 24
    }
  ]
}
qoomon
  • 4,549
  • 1
  • 21
  • 27
  • 1
    Thanks very much for looking at this @qoomon! That was the issue. I used the Docker desktop config interface (Preferences ... Resources ... Network) and edited the Docker subnet value to be 172.31.0.0/16. With that change I'm now able to ping the IP address for the server on the LAN from inside the docker container. – allan Sep 14 '20 at 17:03
  • Hi Allan, are you able to ping any hosts on your LAN/wifi network? – Well Smith Sep 19 '21 at 06:03
  • @qoomon, just curious, is there anything special about the `172.31.0.0/16` address? For instance, can a person use `172.32.0.0/16`? – user1367204 Jan 12 '22 at 19:26
  • @user1367204 it is the private net Class B: 172.16.0.0 to 172.31.255.255 (https://www.ibm.com/docs/en/networkmanager/4.2.0?topic=translation-private-address-ranges) so no your can't or should not use 172.32.0.0/16 subnet for private networks. – qoomon Jan 13 '22 at 20:22
  • I have spent hours trying various suggestions and various combinations of google keywords! This also worked for me. Thank you! In my case docker was using 192.168.65.0/24 but where does it get that from? – The Welsh Dragon Jul 01 '23 at 18:14
  • @TheWelshDragon the resource of the ip is printed to stdout e.g. `Docker Host: $docker_host_ip ($docker_host_source)` – qoomon Jul 03 '23 at 08:47