Failed to get macvlan set up

Docker version 28.2.2, build 28.2.2-0ubuntu1~24.04.1

I’ve been following the steps for macvlan in the documentation, but I fear I must be missing something obvious. I need help debugging this.

My goal is to use Compose to have a typical service of containers on their own net but with one container exposing a LAN IP address – which is why I included compose in the category. But, baby steps…

I have simple container called ub-net:

$ cat Dockerfile
FROM ubuntu:latest
RUN apt update
RUN apt install iproute2 iputils-ping ncat -y
CMD ["sleep","infinity"]

This works, of course:

docker run --rm -it --sysctl net.ipv6.conf.all.disable_ipv6=1--name=foo ub-net:latest ping google.com
PING google.com (142.250.72.142) 56(84) bytes of data.
64 bytes from lax17s49-in-f14.1e100.net (142.250.72.142): icmp_seq=1 ttl=113 time=18.8 ms

My host’s interface and IP:

$ ip route | grep default
default via 192.168.0.1 dev wlp3s0 proto dhcp src 192.168.0.253 metric 600

Update: Forgot to mention I also tried promiscuous mode on the host interface:

$ sudo ip link set dev wlp3s0 promisc on

Now, create a macvlan network and try again:

$ docker network create -d macvlan \
  --subnet=192.168.0.0/24 \
  --gateway=192.168.0.1 \
  -o parent=wlp3s0 \
  test_macvlan
ad660efe198ed1d1020c7138f8024a7fe03e60506b73da5357ad581cad2b53cc

This looks as expected, correct?

$ docker run --rm -it \
 --sysctl net.ipv6.conf.all.disable_ipv6=1 \
 --network test_macvlan \
 --ip 192.168.0.250 \
 --name foo ub-net:latest \
 ip -br route
default via 192.168.0.1 dev eth0
192.168.0.0/24 dev eth0 proto kernel scope link src 192.168.0.250

But, nothing getting out:

$ docker run --rm -it \
 --sysctl net.ipv6.conf.all.disable_ipv6=1 \
 --network test_macvlan \
 --ip 192.168.0.250 \
 --name foo ub-net:latest \
 ping google.com
PING google.com (142.250.72.142) 56(84) bytes of data.
From 3f9f5a02a746 (192.168.0.250) icmp_seq=11 Destination Host Unreachable

And I cannot ping 192.168.0.250 from another host on my LAN. Here’s from my Mac laptop:

$ ping 192.168.0.250
PING 192.168.0.250 (192.168.0.250): 56 data bytes
Request timeout for icmp_seq 0
Request timeout for icmp_seq 1
Here's the docker-compose.yaml I first tried to use:
$ cat docker-compose.yaml
name: My Test

services:

  test_one:
    image: ub-net:latest
    container_name: testone
    hostname: host-testone
    networks:
      mylocal: {}
      my_macvlan: {}
       # ip4_address: 192.168.0.210
       # mac_address: "16:50:8c:86:0a:35"
    cap_add:
      - NET_ADMIN

  test_two:
    image: ub-net:latest
    container_name: testtwo
    hostname: host-testtwo
    networks:
      mylocal: {}


networks:
  mylocal:
    name: mytest_default
    external: true

  my_macvlan:
    name: test_macvlan
    external: true

I’ve seen different examples of how to specify the IP address.

Using this:

    networks:
      mylocal: {}
      my_macvlan:
       ip4_address: 192.168.0.210

generates:

$ docker compose up -d
validating /home/bill/macvlan/docker-compose.yaml: services.test_one.networks.my_macvlan Additional property ip4_address is not allowed

And my network skills are rusty (and limited), but shouldn’t I see the container’s MAC outside the container?

$ docker inspect foo | jq .'[].NetworkSettings.Networks'
{
  "test_macvlan": {
    "IPAMConfig": {
      "IPv4Address": "192.168.0.250"
    },
    "Links": null,
    "Aliases": null,
    "MacAddress": "7a:67:7d:c6:19:f4",
    "DriverOpts": null,
    "GwPriority": 0,
    "NetworkID": "ad660efe198ed1d1020c7138f8024a7fe03e60506b73da5357ad581cad2b53cc",
    "EndpointID": "7cc5d46c866440ea60c07edbc3c3921eb8d5562e1061cefb586ef6a2a0795a89",
    "Gateway": "192.168.0.1",
    "IPAddress": "192.168.0.250",
    "IPPrefixLen": 24,
    "IPv6Gateway": "",
    "GlobalIPv6Address": "",
    "GlobalIPv6PrefixLen": 0,
    "DNSNames": [
      "foo",
      "4a935b7fa5bd"
    ]
  }
}

So, fill the apr table and look for that MAC:

$ ping -b -c1 192.168.0.255
WARNING: pinging broadcast address
PING 192.168.0.255 (192.168.0.255) 56(84) bytes of data.
64 bytes from 192.168.0.145: icmp_seq=1 ttl=64 time=2.99 ms

--- 192.168.0.255 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 2.986/2.986/2.986/0.000 ms

$ arp -a | grep 7a
? (192.168.0.5) at 58:7a:62:25:c6:96 [ether] on wlp3s0

Please share the output of docker info.
While at it, you could also update to the latest docker version, which is 29.1.3 at time being.

Some observations:

Make sure to also specify the --ip-range argument, which defines a range cidr within the subnet that should be used in the macvlan network to automatically assign ip addresses. Make sure it’s outside the range of the network’s dhcp server to avoid collision.

To get it right: your docker host has the ip 192.168.0.253. The network’s router has the 192.168.0.1 and is a seperate device in your network. macvlan child (=what the containers use) and parent (=what the host uses) interfaces can not communicate directly with each other.

Furthermore, the mac address in your compose file is incorrect, replace 16:with 02: (though, the 0 can be anything from hex 0 to f, but the 2 is mandatory to have a valid mac-address). You can not use an arbitrary hex value for the 2nd character of the first two digits. If you use the forum search you should find a topic that shed some light about why (update: this is the topic i had in mind)

Apart from that:
I don’t see anything that would prevent macvlan from working. Since it doesn’t work, I assume that this is a vm or you use a managed switch that freaks out if more than a single mac address is detected on a switch port.If it’s a vm, can you share what platform you use?

Thanks for the response. Updated:

$ docker --version && docker compose version
Docker version 29.1.3, build f52814d
Docker Compose version v5.0.1

I’m running bare metal Ubuntu, so not in a VM (I have Proxmox elsewhere, so maybe I should try there, too.) I do wonder about my network. I’m running TP-Link Omada network.

Oh, crap. I just remembered this Ubuntu is running on an old Macbook Pro but is connected to the network over wifi! I’ll be able to move the laptop in an hour or so and will try again.

One question: What is the correct Compose syntax for specifying the IP address in docker-compose.yaml, similar to how --ip works with docker run?

Ok. Note that I’m specifying the IP address in my docker run commands (and outside my DHCP range).

I got a little lost with that. The docs mentioned that:

  • Containers attached to a macvlan network cannot communicate with the host directly, this is a restriction in the Linux kernel. If you need communication between the host and the containers, you can connect the containers to a bridge network as well as the macvlan. It is also possible to create a macvlan interface on the host with the same parent interface, and assign it an IP address in the Docker network’s subnet.

I’m fine with the container not being able to talk to the host. My interest was exposing a separate IP address that other devices on the LAN can use to connect directly to the container.

But, I didn’t really grasp what all that meant. Am I required to create a new interface on the host?

That is curious. When I was testing last night (trying to configure an IP address in docker-compose.yaml) I also pasted what I thought was the MAC address Docker generated. I had read about generating too many MAC IDs when testing.

We had reports from people that had problems running docker containers on docker installed on the host, caused by apparmor profiles (see: post) specific to Proxmox.

The Proxmox docs recommend using kvm vms to run docker. That’s what I am using without any issue for years in my homelab.

Wifi is indeed the problem: It only handles traffic of the wifi interface’s mac address.

In case of doubt, it is always a good idea to consult the compose file reference:
https://docs.docker.com/reference/compose-file/services/#ipv4_address-ipv6_address

You are not. If you don’t care for host <> macvlan container communication, there is nothing to do, apart from creating the container network with the macvlan driver, and creating containers that are attached to the docker macvlan network.

Make sure to use docker compose and not docker-compose for deployments (see: post)!

Sure was. I “borrowed” that USB-Ethernet adaptor from that laptop about two weeks ago and complete forgot. Blindly copy-n-pasted the interface name. Always something stupid like that.

Thanks for the help.