容器内的节点连接到宿主机上运行的 roscore,而不是容器内的 roscore。

这是一个常见的混合部署场景。以下是详细解决方案:


📋 核心原理

┌─────────────────────────────────────────────────────────────┐
│                      宿主机 (Host)                           │
│  ┌─────────────────┐                                        │
│  │   roscore       │  端口: 11311                            │
│  │   (运行在主机)   │  IP: 宿主机IP 或 host.docker.internal  │
│  └─────────────────┘                                        │
│            ↑                                                │
│            │ 网络通信                                        │
│  ┌─────────┴────────────────────────────────────────┐       │
│  │              Docker 容器                          │       │
│  │  ROS_MASTER_URI=http://宿主机IP:11311            │       │
│  │  rosnode list → 连接到宿主机 roscore             │       │
│  └──────────────────────────────────────────────────┘       │
└─────────────────────────────────────────────────────────────┘

✅ 方案一:使用宿主机 IP(最通用)

步骤 1️⃣:获取宿主机 IP

# Linux 系统
hostname -I | awk '{print $1}'

# 或
ip addr show docker0 | grep "inet\b" | awk '{print $2}' | cut -d/ -f1

# macOS / Windows (Docker Desktop)
# 使用特殊 DNS 名称: host.docker.internal

假设宿主机 IP 是 192.168.1.100

步骤 2️⃣:启动容器并设置环境变量

docker run -d \
  --name ros_node_container \
  --network host \
  -e ROS_MASTER_URI=http://192.168.1.100:11311 \
  -e ROS_HOSTNAME=192.168.1.100 \
  -e ROS_IP=192.168.1.100 \
  ros:noetic-ros-base \
  bash -c "source /opt/ros/noetic/setup.bash && sleep infinity"

关键参数说明:

表格

参数作用必须性
--network host使用宿主机网络,容器直接使用宿主机网络栈⭐ 推荐
ROS_MASTER_URI指向宿主机 roscore 地址⭐ 必须
ROS_HOSTNAME设置节点主机名(用于其他节点连接此节点)建议
ROS_IP设置节点 IP 地址建议

步骤 3️⃣:在容器内执行 rosnode list

docker exec -it ros_node_container bash -c "
  source /opt/ros/noetic/setup.bash && 
  rosnode list
"

预期输出:

/rosout
/其他宿主机上的节点

更多推荐