Using ROS2 over tailscale using Docker’s Host-mode networking

Introduction

This example shows you how to create a docker-compose based container that uses “host-mode” networking. Host mode networking can be simpler because it doesn’t have to be managed by docker itself. Just get your tailscale client up and running on the host computer, and your docker instance can use it.

Instructions

First, go to the administrative interface at tailscale.com and ensure that the magicdns feature is enabled.
This allows your computers to refer to each other by name rather than IP address.

This setup requires that you have downloaded and installed virtualbox on your host machine (the computer running docker). I have tested this with Ubuntu 22.04 and it works.

Next, pick a folder for housing your docker compose file. I have mine setup in ~/docker/ros2-host/

Create a file called docker-compose.yml and paste the following contents inside

version: '2'

services:
  ros1:
    environment:
    - ROS_DOMAIN_ID=0
    - ROS_LOCALHOST_ONLY=0
    - FASTRTPS_DEFAULT_PROFILES_FILE=/root/shared/fast.xml
    - RMW_IMPLEMENTATION=rmw_fastrtps_cpp
    container_name: ros2-talker
    image: osrf/ros:humble-desktop
    hostname: ros-host2
    domainname: test
    network_mode: host
    volumes:
      - ./shared:/root/shared
    command: bash -c "source /opt/ros/humble/setup.bash && ros2 run demo_nodes_cpp talker"
    restart: unless-stopped

create a subfolder called shared. Inside, create a file called fast.xml and paste in the following contents:

Replace [HOSTNAME1] and [HOSTNAME2] with the hostname or IP address of your computers as seen in the tailscale administrative interface. If you anticipate the ip address changing, for example if one of the machines is a docker container without ip address permanence enabled, it is suggested to use the hostname. This is only possible with “magicdns” enabled.

<?xml version="1.0" encoding="UTF-8" ?>
<profiles xmlns="http://www.eprosima.com/XMLSchemas/fastRTPS_Profiles">
    <transport_descriptors>
        <transport_descriptor>
            <transport_id>TailscaleTransport</transport_id>
            <type>UDPv4</type>
        </transport_descriptor>
    </transport_descriptors>
    <participant profile_name="TailscaleSimple" is_default_profile="true">
        <rtps>
            <userTransports>
                <transport_id>TailscaleTransport</transport_id>
            </userTransports>
            <useBuiltinTransports>true</useBuiltinTransports>
            <builtin>
                <initialPeersList>
                    <locator>
                        <udpv4>
                            <address>[HOSTNAME1]</address>
                        </udpv4>
                    </locator>
                    <locator>
                        <udpv4>
                            <address>[HOSTNAME2]</address> 
                        </udpv4>
                    </locator>
                </initialPeersList>
            </builtin>
        </rtps>
    </participant>
</profiles>

Note: you can add more peers as needed to add more devices to your ROS2 network:

<locator>
    <udpv4>
        <address>[HOSTNAMEX]</address> 
    </udpv4>
</locator>

Finally, try out the container using the command:

docker compose up

This will download the required docker images and start the container. The container continuously broadcasts a message over the network to the other computers listed in your fast.xml file.

You can modify the command to listen:

command: bash -c "source /opt/ros/humble/setup.bash && ros2 run demo_nodes_cpp listener"

or to start up your own custom nodes, which is outside of this example.

External Resources

https://adityakamath.hashnode.dev/ros-2-and-vpns

Oter Resources