Access Docker-hosted apps from the Docker host

Accessing Docker-hosted apps from the Docker host

Docker containers attached to a MACVLAN network (only) can not be accessed by the Docker host.

I use a MACVLAN network for a few of my Docker containers so they appear as a separate network device to other devices on the network.

docker network ls | egrep '^NETWORK | mynet192'
NETWORK ID     NAME                   DRIVER    SCOPE
52875db418f4   mynet192               macvlan   local

However, due to a kernel restriction, no MACVLAN child interface (Docker container) is allowed to communicate with the parent interface (Docker host).

The end result is that the Docker host can't use the service(s) running in Docker containers attached to the MACVLAN network

Basic container config

For example, using a simple nginx container definition:

version: "3.8"
services:
  nginx:
    image: nginx:latest
    restart: unless-stopped
    container_name: test123
    ports:
      - 8080:80
    networks:
      mynet192:
        ipv4_address: 192.168.1.222
networks:
  mynet192:
    external: true
docker ps | egrep '^CONTAINER | container_test'
CONTAINER ID   IMAGE           COMMAND                  CREATED             STATUS              PORTS               NAMES
ef3af1a4b240   nginx:latest    "/docker-entrypoint.…"   14 seconds ago      Up 10 seconds                           container_test

No connectivity when using only the MACVLAN network

After the container is started, the Docker host can't access the nginx service.

curl -v 192.168.1.222
*   Trying 192.168.1.222:80...
* connect to 192.168.1.222 port 80 failed: No route to host
* Failed to connect to 192.168.1.222 port 80 after 3064 ms: No route to host
* Closing connection 0
curl: (7) Failed to connect to 192.168.1.222 port 80 after 3064 ms: No route to host

Workaround so the Docker host can use service(s) running in Docker containers

To work around this restriction, create a Docker bridge network, and add this bridge network to the Docker container.

I want some of my containers to have a static IP assigned from this new bridge network, so I restricted the addresses Docker would hand out via DHCP to have the /24 subnet using the --ip-range switch in the network definition.

docker network create -d bridge  --subnet 172.28.0.0/24 --ip-range 172.28.0.128/25 Internal

Updating the compose.yaml file to specify the Internal network in the network definition, and to add it to the container definition, with a specific static IP.

version: "3.8"
services:
  nginx:
    image: nginx:latest
    restart: unless-stopped
    container_name: container_test
    ports:
      - 8080:80
    networks:
      mynet192:
        ipv4_address: 192.168.1.222
      Internal:
        ipv4_address: 172.28.0.222
networks:
  mynet192:
    external: true
  Internal:
    external: true

After adding the Internal network to the container, the Docker host can now access the nginx service running in the container.

curl -v 172.28.0.222
*   Trying 172.28.0.222:80...
* Connected to 172.28.0.222 (172.28.0.222) port 80 (#0)
> GET / HTTP/1.1
> Host: 172.28.0.222
> User-Agent: curl/7.81.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.25.3
< Date: Wed, 01 Oct 2023 20:51:27 GMT
< Content-Type: text/html
< Content-Length: 615
< Last-Modified: Tue, 24 Jul 2023 13:46:47 GMT
< Connection: keep-alive
< ETag: "6537cac7-267"
< Accept-Ranges: bytes
<
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
* Connection #0 to host 172.28.0.222 left intact