TTR Networks

Beginner · Building a network lab on an Apple Silicon Mac · section 7 of 8

Pitfalls and their fixes

✓ Lab-tested 18 October 2026 on macOS 26.5 on Apple M4 Max, Docker Desktop (Linux 7.0.14-linuxkit, arm64), VyOS 2026.10.16-0024-rolling, FRR 10.2.1

These are the problems that actually stopped labs on this Mac, and what fixed each one. Most of them fail quietly, so knowing them in advance saves hours.

What the kernel can't do

Docker Desktop's Linux kernel is built for running containers, not routers, and some features network labs need are simply missing. Checking its configuration (/proc/config.gz) shows, among others:

  • No TCP-MD5 or TCP-AO. BGP passwords can't be enforced. FRR logs Unable to set TCP MD5 option and brings the session up without authentication. The BGP debugging lesson shows exactly this.
  • No VRF. Linux VRFs (ip link add … type vrf) can't be created, so labs that need VRFs on Linux or FRR containers won't work. A VyOS VM has its own kernel, so VRFs inside VyOS are unaffected.
  • No SRv6 lightweight tunnels.
  • Present: MPLS, VXLAN, Geneve, WireGuard, bonding, 802.1Q with VLAN-filtering bridges, nftables, GRE, IPsec (XFRM) and netem for simulating delay and loss.

Features inside a full VM (VyOS) depend on the VM's own kernel, not Docker Desktop's: this list is about containers only.

Never bridge Docker networks together inside a container

The tempting way to build a "switch" is one container with a Linux bridge and one Docker network per port. Don't. Docker's own bridges reflect broadcasts back to the port they came from, so a bridge joining two Docker networks turns the first ARP request into a broadcast storm. It hung Docker Desktop completely, twice, until it was restarted.

For switching labs, build the whole switch fabric inside one container instead: network_mode: none, network namespaces as hosts, veth pairs as cables, and a tap for any VyOS VM. The switching lesson builds a lab exactly this way. (The VyOS start script does bridge Docker interfaces, but each bridge joins one Docker network to one tap, never two networks together, and it turns off MAC learning on the Docker side, because Docker reflects the VM's own broadcasts back and would otherwise teach the bridge the VM's MAC address on the wrong port.)

Smaller traps

SymptomCauseFix
A VM container exits with code 137Out of memory: Docker Desktop's VM ran outRaise Docker Desktop's memory, lower VYOS_MEM, or run fewer VMs
Two VyOS VMs on one network can't talkIdentical MAC addressesA different VM_ID for every VM
VyOS VM freezes under loadMulti-vCPU TCG guestVYOS_SMP=1
DHCPv6 client on VyOS failsNo SMBIOS UUID, so no DUIDKeep the -uuid line in start-vyos.sh
sysctl -w fails: read-only file systemContainers get a read-only /proc/sysprivileged: true, or sysctls: in compose
The first command after boot goes to the login promptVyOS shows login: before it has finished startingAfter wait, run login and check it says logged in; retry if not
docker compose exec hangsA script piped in on stdinPass it as an argument: sh -c "$(cat script.sh)"
exec format errorNo interpreter for amd64 binariesRosetta in Docker Desktop's settings, or the tonistiigi/binfmt install (re-run after restarts)
Can't open configuration file /etc/frr/vtysh.conf on every FRR commandThe FRR image ships without oneMount a one-line vtysh.conf: service integrated-vtysh-config
Unexpected addresses and default routes in containersAn ordinary Docker networkenable_ipv4: false on lab networks
Captured packets bigger than the MTUSegmentation offload in the virtual NICsethtool -K eth0 tso off gso off gro off before capturing
What Docker Desktop's kernel supports (real output)
mac$ docker run --rm alpine sh -c 'zcat /proc/config.gz | grep -E "^(# )?CONFIG_(TCP_MD5SIG|TCP_AO|NET_VRF|MPLS_ROUTING|WIREGUARD|VXLAN|BONDING|BRIDGE_VLAN_FILTERING|VLAN_8021Q|XFRM_USER|NF_TABLES|NET_SCH_NETEM|MACVLAN|GENEVE|NET_IPGRE|IPV6_SEG6_LWTUNNEL)[= ]"'
CONFIG_XFRM_USER=y
CONFIG_NET_IPGRE=y
# CONFIG_TCP_AO is not set
# CONFIG_TCP_MD5SIG is not set
# CONFIG_IPV6_SEG6_LWTUNNEL is not set
CONFIG_NF_TABLES=y
CONFIG_BRIDGE_VLAN_FILTERING=y
CONFIG_VLAN_8021Q=y
CONFIG_NET_SCH_NETEM=y
CONFIG_MPLS_ROUTING=y
CONFIG_BONDING=y
CONFIG_WIREGUARD=y
CONFIG_MACVLAN=y
CONFIG_VXLAN=y
CONFIG_GENEVE=y
# CONFIG_NET_VRF is not set
  • Lines 4–5: No TCP-AO or TCP-MD5: BGP passwords can't be enforced in containers.
  • Line 6: No SRv6 lightweight tunnels.
  • Line 17: No VRFs.
  • Lines 7–16: Everything else a typical lab needs is here: nftables, VLAN-filtering bridges, 802.1Q, netem, MPLS, bonding, WireGuard, macvlan, VXLAN and Geneve, plus GRE and IPsec (lines 2–3).

Check your understanding

You want a switching lab: four hosts on one switch. What's the safe way to build it on Docker Desktop?

  • One container with network_mode: none, namespaces as hosts, veth pairs as cables and a Linux bridge as the switch.
  • A switch container with a Linux bridge joining four Docker networks, one per host.
  • Four hosts on one ordinary Docker network.
  • A VyOS VM with four Docker networks bridged in one bridge group.