ROS 2 Across Containers: the Fast DDS Gotchas
The most confusing bugs in a containerized ROS 2 system are the ones where everything looks connected and nothing works. Our robot had two of them, and both came down to how Fast DDS moves messages across container boundaries. Here is what happened and the two settings that fixed it, so you can recognize the shape before it costs you a day.
Key Insights
- ROS 2’s Fast DDS prefers shared memory between nodes, and separate containers do not share that memory namespace by default
- The fix is a shared IPC namespace for the containers that need to talk, which restores the fast shared-memory transport
- DDS also binds to network interfaces by default, and on one board that is a liability, because a changing address staled our locators and wedged all topic traffic
- Restricting discovery and transport to loopback fixed it, because every node was on the same board anyway
- Commands appearing to arrive while nothing moves is a classic sign that one transport is broken while another still works
Gotcha one: shared memory needs a shared namespace
Running each ROS 2 node in its own container is the right call for a product. It also quietly breaks an assumption Fast DDS makes. For speed, DDS tries to pass messages between local nodes through shared memory rather than the network stack. Two nodes in the same container share that memory naturally. Two nodes in separate containers do not, unless you arrange for them to share the relevant namespace.
Miss it, and you get a maddening state: the nodes discover each other, the topics show up, and yet data does not move the way it should. The fix is to give the containers that need the fast path a shared IPC namespace so the shared-memory transport works across the boundary. Knowing this exists is most of the battle; it is invisible once set and baffling until you know to look.
Gotcha two: DDS binds to interfaces that move
The second one bit us at the worst time. Our robot brings up its own WiFi access point for a booth tablet, which changes the address on its wireless interface. Fast DDS, by default, binds to the network interfaces it finds. When the access point came up and the interface address changed, the DDS locators went stale, and all topic traffic between the containers wedged.
The tell was that the robot’s command buttons still seemed to work, because a separate direct loopback path delivered them, while the camera and telemetry, which ride the DDS topics, froze solid. Commands arriving while nothing happens is the signature of one transport alive and another dead.
The fix, since every node runs on the same board, was to restrict ROS 2 discovery and transport to loopback. Once DDS stopped caring about the wireless interface entirely, the changing address could not stale anything, and the traffic flowed even while the access point was up.
The general lesson
Both gotchas share a root: the DDS defaults are tuned for nodes spread across a network, and a single-board robot with containerized nodes is a different world. On one board, you want the fast local path between containers and you want DDS to ignore the network interfaces whose addresses can shift under it. Set those two things and a whole category of intermittent, transport-level failures disappears.
We have kept the exact configuration out of this post, because the valuable part for your team is knowing these two failure modes exist and what causes them, not a snippet that changes with your topology. Getting the transport right for your specific system, one board or many, is the work we do.
If your ROS 2 system stalls in ways that do not make sense, on the MediaTek Genio or on NVIDIA Jetson, that is exactly the kind of thing we untangle quickly. Tell us what you are building. For the wider stack this came from, see running ROS 2 on the MediaTek Genio and the ROSOrin build overview.
MediaTek Genio Expert Support
Building on MediaTek Genio?
BSP bring-up, GStreamer pipelines, NeuroPilot integration, we've shipped it. Get unblocked fast. One call to scope it, fixed bid to deliver it.
Frequently Asked Questions
Why do ROS 2 nodes in separate Docker containers fail to communicate?
By default ROS 2's Fast DDS tries to use shared memory between nodes for speed, and separate containers do not share the same memory namespace unless you arrange it. So nodes discover each other but messages do not flow as expected. Running the relevant containers with a shared IPC namespace restores the shared-memory path.
What does ROS_LOCALHOST_ONLY do and when should you use it?
It restricts ROS 2 discovery and transport to the loopback interface. When every node runs on one board, that is exactly what you want, because it stops DDS from binding to other network interfaces whose addresses can change. On our robot a changing WiFi address was staling the DDS locators and wedging all topic traffic until we set this.
Why did our robot's commands arrive but nothing happen?
Because two different channels were in play. A direct loopback command path still delivered button presses, so the commands looked like they arrived, while the DDS topic traffic that actually moves data between nodes was wedged by a stale network locator. The lesson is that partial communication can hide a broken transport.
Written by
Andrés CamposCo-Founder & CTO · ProventusNova
8 years deep in embedded systems, from underwater ROVs to edge AI. Andrés leads every technical delivery personally.
Connect on LinkedInRelated Articles
Running ROS 2 on the MediaTek Genio
ROS 2 runs well on the MediaTek Genio, and containers on a custom Yocto image make it reproducible. What the stack looks like and the gotchas to expect.
Camera Lifecycle in Docker: SIGINT vs SIGTERM
Our ROS 2 camera container would not restart cleanly, and the camera got stuck. The cause was the stop signal. Why SIGTERM broke it and SIGINT fixed it.
Driving a Mecanum Robot from ROS 2
Our mecanum robot strafed sideways when told to go forward. The cause was a diagonal wheel pair wired backwards. How mecanum drive works and how to catch it.
MediaTek Genio for robotics edge AI: inference, camera, BSP reality
Is MediaTek Genio viable for robotics edge AI? Honest assessment of inference latency, camera pipeline, ROS 2 support, and BSP limitations for robotics builds.