ROS2 across Podman containers
Fast DDS (the default ROS2 middleware in Jazzy) uses UDP multicast to discover other nodes, but transfers data via shared memory (/dev/shm) when both nodes are on the same machine. This avoids serialisation overhead for high-bandwidth topics like point clouds.
Splitting ROS nodes into their own containers is a natural way to isolate subsystems — one container per sensor driver, one for localisation, etc. With --net host, discovery works fine across containers. But rootless Podman gives each container its own IPC namespace, which means its own /dev/shm. One container writes data to shared memory and tells another to read it, but that memory segment doesn’t exist in the other container’s namespace. The read silently fails — ros2 topic list shows everything, ros2 topic echo hangs forever.
The fix is to share the IPC namespace between containers using --ipc shareable on the first container and --ipc container:<name> on the rest:
podman run --net host --ipc shareable --name my-publisher ...
podman run --net host --ipc container:my-publisher --name my-subscriber ...
podman-compose doesn’t support this
The Docker Compose equivalent is:
services:
publisher:
ipc: shareable
subscriber:
ipc: service:publisher
This works with docker compose, but podman-compose silently ignores the ipc directive — it appears in podman-compose config output but isn’t passed through to podman run. Still an open issue since 2020, confirmed broken as of v1.5.0. For now you need a shell script with direct podman run commands, or use Docker Compose.
Diagnosing the problem
If you’re not sure whether IPC namespaces are shared, compare the namespace IDs:
podman exec container-a ls /proc/self/ns/ipc -la
# ipc:[4026533574]
podman exec container-b ls /proc/self/ns/ipc -la
# ipc:[4026533663] ← different = broken
If they differ, the containers have separate /dev/shm and Fast DDS data transfer won’t work between them.