Setup docker container eclipse-mosquitto to use ipvlan and access it from other devices

Posted by Felipe Arturo López Bonilla on

While working on an MQTT data transmission project, I set up an eclipse-mosquitto docker container as a broker on my laptop. However, with this configuration I could not connect to the broker from other devices since the container's network is separated from my local network. Luckily, after some web searching, I found a blog post that sets a configuration that integrates the container into the same local network. This will allow to connect to that broker from other devices like an ESP32.

Taking inspiration from the blog post at Using Docker macvlan networks :: blog.oddbit.com, I'll describe the steps to create an eclipse-mosquitto container that connects to your local network. I highly recommend reading the original post first.

Create an ipvlan docker network

According to the documentation of the driver and docker [1][2], one advantage is that it connects directly to the host interface. This allows us to set an IP address on the same network shared by the host machine and the router. The configuration we want to achive is show in the following diagram.

Network diagram

In my case I assgined to the container the address 192.168.2.111 so its reachable from any device, even from the host machine. Your router's IP address may be different so modify the IP address to match your local network.

First, we have to create create a docker network. To do that run the following command:

docker network create -d ipvlan -o parent=eno1 \
  --subnet 192.168.2.0/24 \
  --gateway 192.168.2.1 \
  --ip-range 192.168.2.110/28 \
  --aux-address 'host=192.168.2.110' \
  ipvlan1

What we are doing is to reserve 15 ip addresses, from 192.168.2.110 to 192.168.2.114 and reserve the address 192.168.2.110 for use by the host interface.

IMPORTANT: You must check your router can assign the IP addresses you defined in the docker network configuration becuase if that's not possible then you will not be able to connect to the container.

Setup a bridge between the host machine and the container

The ipvlan driver isolates the container's network; therefore we cannot ping to any container that uses the network we just created from the host machine. To address this limitation we need to create a bridge between the host machine (in my case, my laptop) and the eclipse-mosquitto container.

Run the following commands to create and configure the bridge:

sudo ip link add ipvlan1 link eno1 type ipvlan # Default mode bridge l3
sudo ip addr add 192.168.2.110/32 dev ipvlan1 # Assign the IP address we reserved from the docker network
sudo ip link set ipvlan1 up
sudo ip route add 192.168.2.0/24 dev ipvlan1

Confirm that the bridge was created

Execute the following commands to confirm that the bridge was created and that we have added the route to our docker network:

ip addr show ipvlan1
5: ipvlan1@eno1:  mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000
    link/ether ac:e2:d3:7b:d6:35 brd ff:ff:ff:ff:ff:ff
    inet 192.168.2.110/32 scope global ipvlan1
       valid_lft forever preferred_lft forever
    inet6 fe80::ace2:d300:17b:d635/64 scope link 
       valid_lft forever preferred_lft forever
ip route
default via 192.168.2.1 dev eno1 proto dhcp src 192.168.2.191 metric 100 
169.254.0.0/16 dev eno1 scope link metric 1000 
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1 linkdown 
192.168.2.0/24 dev ipvlan1 scope link 
192.168.2.0/24 dev eno1 proto kernel scope link src 192.168.2.191 metric 100

Start the eclipse-mosquitto container with the new network

Finally, create a new docker-compose.yml file with the following configuration:

version: "3"
services:
  mosquitto:
    image: eclipse-mosquitto:latest
    container_name: mosquitto
    networks:
      external-net:
        ipv4_address: 192.168.2.111
    volumes:
      - /home/ubuntu/mqtt/mosquitto/config:/mosquitto/config
      - /home/ubuntu/mqtt/mosquitto/data:/mosquitto/data
      - /home/ubuntu/mqtt/mosquitto/log:/mosquitto/log
    restart: unless-stopped

networks:
  external-net:
    name: ipvlan1
    external: true

Save the file and on the same directory execute the following command to create the container:

docker-compose up -d

Test the eclipse-mosquitto container

First, try to ping the container to verify you can reach the broker:

ping -c4 192.168.2.111

To test the broker I downloaded the following MQTT client: MQTT-c-pub-sub. To compile the project you need cmake installed on your computer.

Open a terminal and run the following command to see the log of the eclipse-mosquitto broker:

docker exec -it mosquitto tail -f /mosquitto/log/mosquitto.log

On a different terminal run the MQTT client to publish the messages. The default topic is hello/world:

./mqttpub -i 192.168.2.111

On the mosquitto's log you should see something similar to this:

2024-03-30T19:18:33: New connection from 192.168.2.110:37114 on port 1883.
2024-03-30T19:18:33: New client connected from 192.168.2.110:37114 as default_pub (p1, c1, k30).
2024-03-30T19:18:43: Client default_pub disconnected.

References