Docker 容器双网卡访问物理雷达网络教程
作者: 陈梓洋
环境: ubuntu 22.04lts
时间: 2025年4月29日
Docker 容器双网卡访问物理雷达网络教程
这个教程适用于这样的场景:容器保留原有 ROS 通信网络(如 bridge 网络),同时需要访问一个物理设备(如雷达)所在的局域网(如 192.168.1.x 网段)。
关键目标是:不改动原容器网络结构,仅新增一块可以访问雷达的“第二网卡”。
建立 docker自定义结构
1. 建立 my_bridge_network(ROS 容器通信用)
我们首先创建一个用于容器间 ROS 通信的桥接网络 my_bridge_network
。这个网络不会连接物理设备,但非常适合多个容器之间共享 ROS master。
执行:
docker network create \--driver bridge \--subnet=172.18.0.0/16 \my_bridge_network
2. 启动 ROS Master 容器
可以用官方 ros:noetic
镜像运行一个 ROS master 容器,挂载到刚才创建的 my_bridge_network
上:
docker run -dit \--network my_bridge_network \--name ros_master_container \ros:noetic \roscore
这一步会启动 roscore
并在容器内部监听 11311
端口,作为整个 ROS 网络的主节点。
3. 启动 HAP 驱动容器(挂入 my_bridge_network)
然后运行实际驱动或应用逻辑的容器,同样挂载到 my_bridge_network
,并通过环境变量连接 ROS master:
docker run --privileged -it \-e NVIDIA_DRIVER_CAPABILITIES=all \-e NVIDIA_VISIBLE_DEVICES=all \--volume=/home/dw/docker/hap:/home/catkin_ws/src \--volume=/tmp/.X11-unix:/tmp/.X11-unix:rw \--network my_bridge_network \--ipc=host \--shm-size=1gb \--name=hap_driver_container \--env="DISPLAY=$DISPLAY" \--env="ROS_MASTER_URI=http://ros_master_container:11311" \--env="ROS_DOMAIN_ID=28" \ros:noetic /bin/bash
以上步骤完成后,你的 ROS 系统就已经建立了一个基础的通信网络:
- 所有容器都连在
my_bridge_network
上; - 使用容器名
ros_master_container
替代 IP,方便维护; - 后续只需确保 ROS master、topic、TF、参数服务器都通过这个网络同步即可。
下一部分将介绍如何在此结构下单独为 HAP 容器追加一张物理雷达网卡,用于直接访问外部设备。
双网卡
1. 宿主机准备:创建 macvlan 网络
假设:
- 宿主机连接雷达的网卡为
enp44s0
- 雷达 IP 为
192.168.1.100
- 我们分配容器使用的 IP 为
192.168.1.242
- 网关是
192.168.1.1
(可选)
在宿主机执行:
docker network create -d macvlan \--subnet=192.168.1.0/24 \--gateway=192.168.1.1 \-o parent=enp44s0 \radar_macvlan
这一步创建了一个 macvlan 网络,允许容器“直接插到”物理网段上。
2. 给已运行的容器挂上第二块网卡
容器原本就运行在 my_bridge_network
上(不要动它),现在追加一张网卡:
docker network connect \--ip 192.168.1.242 \radar_macvlan \hap_driver_container
这条命令不会替换原来的网络,只是添加第二块网卡(通常在容器里叫
eth1
)。
3. 宿主机打开混杂模式(允许转发 MAC)
这一步必须做,否则容器的 ARP 请求可能会被物理网卡过滤掉。
sudo ip link set enp44s0 promisc on
确认开启:
ip link show enp44s0 | grep PROMISC
4. 宿主机自身也加入 macvlan 网络(中继 + ARP)
即使开了 promisc,容器和雷达之间也可能互不认识。这一步让宿主变成中继节点。
sudo ip link add radar0 link enp44s0 type macvlan mode bridge
sudo ip addr add 192.168.1.241/24 dev radar0
sudo ip link set radar0 up
注意:容器和 radar0 不能使用相同 IP;最好选
.241
等不冲突的地址。
5. 容器内部配置路由(重要)
进入容器:
docker exec -it hap_driver_container bash
配置 eth1:
ip link set eth1 up
ip addr add 192.168.1.242/24 dev eth1
ip route add 192.168.1.0/24 dev eth1
验证:
ping 192.168.1.100
如果能通,说明雷达已经可以被访问了。
6. 可选:提交镜像,保存当前环境
docker commit hap_driver_container hap_driver_ready:latest
7. 最后手段(未经过测试)
在宿主机上新增一个 macvlan 子接口(macvlan-to-host)
即便开启了 promisc,有时宿主机到容器的流量仍然不透。可以创建一个与容器同网段的 macvlan 接口,让宿主机本身也以 macvlan 身份“加入”这个网段:
# 1. 建立 macvlan 子接口 radar0
sudo ip link add radar0 link enp44s0 type macvlan mode bridge# 2. 分配一个可用 IP(避开 .100 和 .242)
sudo ip addr add 192.168.1.241/24 dev radar0# 3. 启动接口
sudo ip link set radar0 up# 4. 验证
ip addr show radar0
ping 192.168.1.100 # 此时宿主机也用 macvlan 身份 ping,应能通
原理:宿主机本身也变成了这个 macvlan 网络的“节点”,能正确回应 ARP 并中继流量给容器。
总结
这个结构下,你的容器拥有两张网卡:
- eth0 → 保持原有 ROS 网络结构(bridge / ros_master 互通)
- eth1 → 单独访问物理雷达网络,不依赖 host 网络,不干扰 ROS
以后可以直接挂 radar_macvlan
网络给其他容器,实现多个模块共享雷达数据。
附记:
由于**LiDAR_IMU_Init**根本没有ros2版本,本人也无法迁移这种大型项目。
于是我在 ubuntu 22.04lts内构建了4个ros1 docker。
hap_driver_container
docker run --privileged -it \-e NVIDIA_DRIVER_CAPABILITIES=all \-e NVIDIA_VISIBLE_DEVICES=all \--volume=/home/dw/docker/hap:/home/catkin_ws/src \--volume=/tmp/.X11-unix:/tmp/.X11-unix:rw \--network my_bridge_network \--ipc=host \--shm-size=1gb \--name=hap_driver_container \--env="DISPLAY=$DISPLAY" \--env="ROS_MASTER_URI=http://ros_master_container:11311" \--env="ROS_DOMAIN_ID=28" \ros:noetic /bin/bash
wit_driver_container
docker run --privileged -it \-e NVIDIA_DRIVER_CAPABILITIES=all \-e NVIDIA_VISIBLE_DEVICES=all \--volume=/home/dw/docker/wit:/home/catkin_ws/src \--volume=/tmp/.X11-unix:/tmp/.X11-unix:rw \--network my_bridge_network \--ipc=host \--shm-size=1gb \--name=wit_driver_container \--env="DISPLAY=$DISPLAY" \--env="ROS_MASTER_URI=http://ros_master_container:11311" \--env="ROS_DOMAIN_ID=28" \ros:noetic /bin/bash
lidar_imu_container
docker run --privileged -it \-e NVIDIA_DRIVER_CAPABILITIES=all \-e NVIDIA_VISIBLE_DEVICES=all \--volume=/home/dw/docker/li_init:/home/catkin_ws/src \--volume=/tmp/.X11-unix:/tmp/.X11-unix:rw \--network my_bridge_network \--ipc=host \--shm-size=1gb \--name=li_init \--env="DISPLAY=$DISPLAY" \--env="ROS_MASTER_URI=http://ros_master_container:11311" \--env="ROS_DOMAIN_ID=28" \li_init:1.0 /bin/bash
ros_master_container
docker run --privileged -it \-e NVIDIA_DRIVER_CAPABILITIES=all \-e NVIDIA_VISIBLE_DEVICES=all \--volume=/home/dw/docker/ros_master:/home/catkin_ws/src \--volume=/tmp/.X11-unix:/tmp/.X11-unix:rw \--network my_bridge_network \--ipc=host \--shm-size=1gb \--name=ros_master_container \--env="DISPLAY=$DISPLAY" \--env="ROS_MASTER_URI=http://192.168.1.50:11311" \ros:noetic /bin/bash
最后终于可以同时连接串口imu和网口雷达,做标定测试了!