Multi-Container Robotics with Docker Compose: Connecting Services and Using the Host GUI

Containers are a powerful tool in the world of robotics software engineering, allowing us to isolate and run our applications in a predictable and reproducible environment. Previously, we looked at running individual containers, but what if we need to run multiple containers and enable communication between them? This is where the true strength of containers shines. By utilizing tools like Docker Compose, we can define a multi-container application in a single file, specifying how each container should be built and linked. This capability enables us to orchestrate complex systems and streamline our development process. For example, we could have one container running our vision processing algorithm while another container handles motion planning, all working together seamlessly.

Furthermore, there are scenarios where we may want our containers to access the host system's GUI, such as when we need to visualize data or interact with graphic interfaces. This feature can be essential when developing robotics applications that require real-time monitoring or user input.

Let's run 2 containers separately.

Run the container responsible for the Simulation of UR5 in Gazebo and MoveIt, using the GUI of the host:

xhost +si:localuser:root
docker run --rm -it --name ur5sim \
   --net=host \
   -e DISPLAY=$DISPLAY \
   -e QT_X11_NO_MITSHM=1 \
   -e RMW_IMPLEMENTATION=rmw_cyclonedds_cpp \
   -e ROS_DOMAIN_ID=0 \
   -v /tmp/.X11-unix:/tmp/.X11-unix:rw \
   -v /dev/dri:/dev/dri \
   -v ~/ur5_ws_docker/src:/workspaces/app_ws/src \
   ur5_simulation_docker:gui

now open another terminal and run the realsense container, as we did in the last lesson:

xhost +si:localuser:root
cd ${ISAAC_ROS_WS}/src/isaac_ros_common && \
./scripts/run_dev.sh -d ${ISAAC_ROS_WS}

These 2 containers runs separately, stand alone. Now let's see how to put them in communication and sharing the host GUI.

When working with ROS 2 for developing robotics software, it's essential to have a good understanding of how to create a docker-compose.yml file.

This file serves a similar purpose to a ros2 launch file in that it allows us to run nodes and orchestrate them in a coherent manner. Just like how a launch file specifies which nodes to run and how they communicate with each other, a docker-compose.yml file defines the services (containers) to be used and their configurations. This setup is crucial for deploying complex robotics systems where multiple nodes need to work together seamlessly.

You can see that we have 2 services:

ur5_moveit:
image: ur5_simulation_docker:gui
container_name: ur5_moveit
network_mode: host
privileged: true
tty: true
stdin_open: true
environment:
- DISPLAY=$DISPLAY
- QT_X11_NO_MITSHM=1
- RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
- ROS_DOMAIN_ID=0
- GAZEBO_MASTER_URI=http://127.0.0.1:11345
volumes:
- ${HOME}/ur5_ws_docker:/workspaces/app_ws
command: >
bash -lc "
source /opt/ros/humble/setup.bash &&
source /workspaces/app_ws/install/setup.bash &&
ros2 launch ur5_simulation spawn_ur5_camera_gripper_moveit.launch.py"
restart: unless-stopped

and this container for the realsense using the real camera:

realsense_camera:
image: isaac_ros_dev-x86_64:latest
container_name: realsense
network_mode: host
privileged: true
runtime: nvidia
environment:
- NVIDIA_VISIBLE_DEVICES=all
- NVIDIA_DRIVER_CAPABILITIES=all
- RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
- ROS_DOMAIN_ID=0
volumes:
- /dev:/dev
- /run/udev:/run/udev
- ${ISAAC_ROS_WS}:/workspaces/isaac_ros_dev
working_dir: /workspaces/isaac_ros_dev
command: >
bash -lc "source /opt/ros/humble/setup.bash &&
ros2 launch realsense2_camera rs_launch.py camera_name:=real_camera qos_image:=SENSOR_DATA enable_color:=true enable_depth:=true pointcloud.enable:=true"
restart: unless-stopped



When working with ROS and Docker, running the command "docker compose up" might not always work as expected. This is especially true when dealing with containers that require interactive GUI interfaces, such as the realsense container. Docker compose is primarily designed to work with containers in a headless mode, meaning it may not support interactive graphical applications out of the box. To overcome this limitation and ensure the proper functionality of the realsense container, we need to take an alternative approach.

To resolve the issue and successfully run the realsense container, we can use the "docker run" command specifically for the container that needs the interactive GUI, in this case, the ur5_moveit service.

By running the individual container with the necessary parameters for GUI support, we can ensure that it functions correctly within the Docker environment. Once the ur5_moveit service is running independently using the "docker run" command, we can proceed to start the remaining containers, including the realsense container, using the standard "docker-compose up" command.

Then run this comman:

sudo mkdir -p /workspaces/app_ws
sudo ln -s /home/fra/ur5_ws_docker/install /workspaces/app_ws/install

this allows your container ur5_moveit to get the meshes from your workspace in suche a way that the rviz2 that you are about to run from the host, can see the meshes that "compose" the robot_description topic, so you can see the robot.

Then put these environmental variable and run rviz2

export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
export ROS_DOMAIN_ID=0
rviz2

these command allows your data to be seen from DDS.

As a recap, to make this architecture work properly:

1) open a terminal and run the container responsible of the simulation with MoveIt

xhost +si:localuser:root
docker run --rm -it --name ur5sim \
   --net=host \
   -e DISPLAY=$DISPLAY \
   -e QT_X11_NO_MITSHM=1 \
   -v /tmp/.X11-unix:/tmp/.X11-unix:rw \
   -v /dev/dri:/dev/dri \
   -v ~/ur5_ws_docker/src:/workspaces/app_ws/src \
   ur5_simulation_docker:gui

2) run the docker compose that runs the service Realsense in headless mode:

docker compose up

3) Open terminal and allow the container to see the meshes of your workspace:

sudo mkdir -p /workspaces/app_ws
sudo ln -s /home/fra/ur5_ws_docker/install /workspaces/app_ws/install

4) Setup the enviromental variable on the terminal to allows DDS to share all the data that are coming from 2 containers:

export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
export ROS_DOMAIN_ID=0
rviz2

in the Rviz2 GUI from your host, add the feature that you need to see the simulation environment and the data that the Realsese is streaming





Complete and Continue  
Discussion

0 comments