Skip to content

Instantly share code, notes, and snippets.

@Ostico
Last active March 4, 2024 10:20
Show Gist options
  • Save Ostico/5c41367f47d99919f41cb915530daa7b to your computer and use it in GitHub Desktop.
Save Ostico/5c41367f47d99919f41cb915530daa7b to your computer and use it in GitHub Desktop.
Give your host access to Docker containers with macvlan

Give your host access to Docker containers with macvlan

Let's assume you have a macvlan interface running.

#$ docker network inspect test_loc-macvlan

[
    {
        "Name": "test_loc-macvlan",
        "Id": "2844ab2bdb2b1bd382afa7a6850acab44cfd7e1318f0fa6a02b5f8d4db410272",
        "Created": "2024-02-26T16:28:24.771033801+01:00",
        "Scope": "local",
        "Driver": "macvlan",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "192.168.100.0/22",
                    "IPRange": "192.168.100.0/22",
                    "Gateway": "192.168.100.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": true,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "4d50cbee0ebaa9cf452f58027a919c3ae5b557cceaf27d24a33e13ff77d133c6": {
                "Name": "test-node-1",
                "EndpointID": "9fb34429fed32ddfc0168085c417a0471d06c35af79c2aad72bc8c07a00c82a3",
                "MacAddress": "02:42:c0:a8:64:64",
                "IPv4Address": "192.168.100.100/22",
                "IPv6Address": ""
            },
            "7f0557509b512af7b0f47b853e960775e40c40fe1e705224136407d1caebd324": {
                "Name": "test-node-2",
                "EndpointID": "8cdcef8f553fa2982c7def4947adce3f78af368a466e2ddf5089b398223fa16f",
                "MacAddress": "02:42:c0:a8:65:64",
                "IPv4Address": "192.168.101.100/22",
                "IPv6Address": ""
            },
            "9b36a929206a14b9e8c14d9cc4d46ddf13dbaf4348870f17a5f35ba601f0ce69": {
                "Name": "test-node-3",
                "EndpointID": "b00443d23555f18f18e75a8698f33d35b1797858d69db1b2f407e5d7ca28a17b",
                "MacAddress": "02:42:c0:a8:66:64",
                "IPv4Address": "192.168.102.100/22",
                "IPv6Address": ""
            }
        },
        "Options": {
            "parent": "enx803f5d0984ac"
        },
        "Labels": {
            "com.docker.compose.network": "loc-macvlan",
            "com.docker.compose.project": "cluster-test",
            "com.docker.compose.version": "1.29.2"
        }
    }
]

In my case the macvlan is in the range 192.168.100.0/22,

Usable Host IP Range: 192.168.100.1 - 192.168.103.254

My 3 test nodes are in such range, one for different C class:

192.168.100.100
192.168.101.100
192.168.102.100

Let's start

Identify your network interface; it can be eth0 or another interface. For me, it is enx803f5d0984ac. Then, add a new interface alias to it.

sudo -sE
ip link add loc-interface link enx803f5d0984ac type macvlan mode bridge

Now check the just created interface:

#$ ip a s

22: loc-interface@enx803f5d0984ac: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 56:a1:69:6a:40:da brd ff:ff:ff:ff:ff:ff

Let's assign a valid ip to my new interface in the range of those of the macvlan 192.168.100.0/22.

You MUST be sure that such ip is not used AND it will never be used by any container AND it will not assigned automatically to any device by your router.

ip addr add 192.168.103.1/32 dev loc-interface

Check again your new interface, it should have the associated ip:

#$ ip a s

22: loc-interface@enx803f5d0984ac: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether 56:a1:69:6a:40:da brd ff:ff:ff:ff:ff:ff
    inet 192.168.103.254/32 scope global loc-interface
       valid_lft forever preferred_lft forever

Now bring up the interface:

ip link set loc-interface up

Check again, it should be up:

#$ ip a s

22: loc-interface@enx803f5d0984ac: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 56:a1:69:6a:40:da brd ff:ff:ff:ff:ff:ff
    inet 192.168.103.1/32 scope global loc-interface
       valid_lft forever preferred_lft forever
    inet6 fe80::54a1:69ff:fe6a:40da/64 scope link 
       valid_lft forever preferred_lft forever

Now, we must tell to our host to route all traffic directed toward the docker macvlan test_loc-macvlan to our new interface instead:

ip route add 192.168.100.0/22 dev loc-interface

Let's check the route table:

#$ ip route show

....
192.168.100.0/22 dev loc-interface scope link

Done, now you can communicate directly with your containers from the host.

*** NOTE ***

  • If the Docker cluster was active, it needs to be restarted to enable communication.
  • The changes made to the host interface are not permanent and will be reverted after reboot. Therefore, you must create a script to set the interface and routes again when the host restarts.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment