Docker Containers on your VLAN

This was previously published on Medium and in an effort to own my content, republished here.

Host only network has its limitations with the fact that its technically your docker host acting as a bridge for your contains to get access to the physical network connected to the host.

This means you have to do extra work to expose services on your containers with the problem of sometimes running into situations where there are port conflicts because some other container has already used that port. There are also 2 different ways to address your container: either via the host for things connected to your host, or the IP address your container uses to connect to the docker network.

Having your containers connected directly to your physical network has immense benefits, chief of which is having your router knowing how to route traffic between containers on the same host as well as all other devices on the network. Also port conflicts disappear because the containers are “connecting directly” to the physical network

I’m going to use my Pi-Hole setup as an example of how I’ve setup my Docker containers to use VLANs on my network. This guide assumes that you already have a VLAN aware network and have one setup for your Docker host to use with your containers.

macvlan Docker Network

Your containers can be attached to various Docker networks, in the case of wanting to have them use IP addresses and route using a particular VLAN (basically 802.1q trunk bridge mode), you will have to create a docker network using the macvlan driver.

docker network create -d macvlan \
  --subnet=192.168.69.0/24 \
  --gateway=192.168.6.1 \
  -o parent=eth0.69 sixtynine
  • macvlan is the driver you are using here to get 802.1q trunk bridge mode
  • 192.168.69.0/24 is the subnet that is specified for your VLAN
  • 192.168.69.1/2 is the gateway
  • eth0.69 is the interface that this is network is supposed to use. eth0 being the phsyical interface (yours might be named differently) and 69 being the VLAN identifier
  • sixtynine is the name of the docker network

Pi-Hole

Getting Pi-Hole configured to use the macvlan network is pretty easy.

docker run -d \
    --name pihole \
    -p 53:53/tcp -p 53:53/udp -p 80:80 \
    -e ServerIP="192.168.69.69" \
    -e VIRTUAL\_HOST=pihole.something.cool \
    -e TZ=America/Los\_Angeles \
    -e DNS1=192.168.1.1 \
    -e DNS2=127.0.0.1 \
    -e DNSMASQ\_LISTENING=all \
    --dns=1.1.1.1 \
    --dns=1.0.0.1 \
    --cap-add=NET\_ADMIN \
    --hostname=pihole.something.cool \
    --ip=192.168.69.69 \
    --net=sixtynine \
    --restart=always \
    pihole/pihole:latest
  • --ip=192.168.69.69 is the IP address for the container. This is the one thing that has to be done because the container itself actually does not request an IP address via DHCP
  • --net=sixtynine is the docker network name that we previously specified when we created the macvlan network
  • --dns=… is the override for DNS that docker is configured. I usually specify this just as a precaution. Specially for Pi-Hole, I use an actual DNS server since Pi-Hole needs DNS resolution to fetch the ad block lists when it starts up

Been messing with docker-compose lately so here’s the exact same setup as above, but in a docker-compose.yml. The only caveat for your VLAN setup is that the gateway has to be on x.y.z.1.

networks:  
  default:  
    attachable: true  
    driver: macvlan  
    driver_opts:  
      parent: eth0.69  
    ipam:  
      config:  
        - subnet: 192.168.69.0/24  
    name: sixtynine  
services:  
  pihole:  
    cap_add:  
      - NET_ADMIN  
    container_name: pihole  
    dns:  
      - 1.1.1.1  
      - 1.0.0.1  
    environment:  
      - DNS1=127.0.0.1  
      - DNS2=192.168.1.1  
      - DNSMASQ_LISTENING=all  
      - ServerIP=192.168.69.69  
      - TZ=America/Los_Angeles  
      - VIRTUAL_HOST=pihole.something.cool  
    hostname: pihole.something.cool  
    image: pihole/pihole:latest  
    networks:  
      default:  
        ipv4_address: 192.168.69.69  
    ports:  
      - "53:53"  
      - "80:80"  
    restart: always
version: '3.7'

Setting up containers to use macvlan for networking is actually pretty straight forward once its understood that this is no more than a bridge into the the VLAN that exists on the physical network.

Versus what host networking is: a bridge into the host which is a masquerade for your containers.