February 21, 2022 by Daniel F Dickinson3 minutes
When using Docker to containerize internal services like Samba, LLMNR, or mDNS a.k.a Bonjour one may find that the standard Docker model of using specific unicast ports forwards, is insufficient.
Normally when using Docker one only wants specific unicast ports forwarded, so the standard Docker paradigm of using NAT to forward ports to the container works. However, when using Docker to containerize internal services like Samba (which needs a combination of unicast and broadcast UDP), LLMNR (Windows multicast address resolution), or mDNS aka Bonjour (Apple multicast address resolution) one may find that the standard Docker model is insufficient.
If one doesn’t need the Docker host, or virtual machines on the Docker host, to access the container then one can simply use Docker ipvlan L2 networks.
For the exceptions, you might be interested in the configuration below.
docker create
command to create an ipvlan L2 network. Docker instances that wish to use the
bridge attach to the docker network so created.br0.netdev
[NetDev]
Kind=bridge
Name=br0
br0.network
[Match]
Name=br0
[Link]
ARP=yes
[Network]
Gateway=192.168.1.1 # If you have a different gateway, use that address
DHCP=no
DNS=192.168.1.1 # If your DNS server is at a different address, use that address
IPv6AcceptRA=no
LLMNR=yes
IPForward=yes
LLDP=no
EmitLLDP=no
[Address]
Address=192.168.1.XXX/24 # Obviously use the actual IP address for the physical host for 192.168.1.XXX
eth0.network
eth0
should be the actual physical network interface on your Linux host (e.g.
enp2s0
) and MACAddress
should be set the real MAC address of that interface.
[Match]
MACAddress=11:22:33:44:55:66
Name=eth0
[Link]
ARP=yes
[Network]
Bridge=br0
LinkLocalAddressing=no
We use vems0
as the veth interface that is a member of the bridge and vedms0
as the interface for the Docker Network
vems0.netdev
[NetDev]
Name=vems0
Kind=veth
[Peer]
Name=vedems0
vems0.network
[Match]
Name=vems0
[Link]
ARP=yes
[Network]
Bridge=br0
LinkLocalAddressing=no
BindCarrier=br0
vedms0.network
NB: vedms0.netdev
is not needed
[Match]
Name=vedms0
[Link]
ARP=yes
[Network]
BindCarrier=br0
LinkLocalAddressing=no
In this example we give the Docker network the 192.168.1.1 to 192.168.1.127 range (192.168.1.0/25). If you have a router giving out DHCP addresses on this network, you should make sure to exclude that range from addresses given to other hosts (e.g. laptops, mobile devices, IoT devices, etc) that are also on the network.
docker network create -d ipvlan \
--subnet=192.168.1.0/24 \
--gateway=192.168.1.1 \
--ip-range=192.168.1.0/25 \
-o ipvlan_mode=l2 \
-o parent=vedms0 newnet_name
For this example we assume the use of docker-compose
.
docker-compose.yml
Obviously this omits the non-network configuration that you would need.
networks:
newnet_name:
external: true
services:
someservice:
networks:
newnet_name:
ipv4_address: 192.168.1.XXX # Where you use the LAN address to assign to the container
Obviously this omits the non-network configuration that you would need.
networks:
newnet_name:
external: true
stacknet:
driver: bridge
services:
someservice:
networks:
newnet_name:
ipv4_address: 192.168.1.XXX # Where you use the LAN address to assign to the container
stacknet:
supportservice:
networks:
stacknet:
E.g. docker-compose up --build -d
Now you should be able to access someservice via it’s ipv4 address on any TCP/UDP port or other IP-based protocol.