Files
ROS2_learn/doc/85-docker.md
T
2026-08-04 18:14:49 +08:00

12 KiB

85 · Docker 容器化开发(完全指南)

目标:吃透本仓库 Docker 配置,知道每行在做什么,能改能扩,能在 Win/macOS/Linux 一致跑 ROS2。


目录


1. 为什么用 Docker

痛点 Docker 怎么解
Linux/Windows/macOS 行为差异 镜像固定 Linux,行为一致
ROS2 apt 装一堆,污染系统 容器内隔离
团队协作"在我机器能跑" 镜像统一
升级 ROS 版本代价大 换镜像就行
跨语言/多版本测试 同一镜像多容器

本仓库基于 osrf/ros:humble-desktop(OSRF 官方维护):

  • ROS2 Humble 完整运行时
  • 默认 RMW: rmw_fastrtps_cpp
  • 自带 RViz2 / rqt / colcon / rosdep

2. 镜像构建

2.1 Dockerfile

docker/Dockerfileosrf/ros:humble-desktop 之上加:

FROM osrf/ros:humble-desktop

ENV DEBIAN_FRONTEND=noninteractive
ENV ROS_DISTRO=humble
ENV WORKSPACE=/root/ros2_ws

RUN apt-get update && apt-get install -y \
    python3-colcon-common-extensions \
    python3-pip \
    nano \
    curl \
    && rm -rf /var/lib/apt/lists/*

RUN pip3 install -U colcon-argcomplete colcon-common-extensions

RUN echo 'source /opt/ros/humble/setup.bash' >> /root/.bashrc && \
    echo 'source /usr/share/colcon_argcomplete/hook/colcon-argcomplete.bash' >> /root/.bashrc

WORKDIR ${WORKSPACE}

CMD ["bash"]

2.2 构建

# Windows
docker compose -p ros2 -f D:\xs\ros2\docker\docker-compose.yml build
# Linux
docker compose -p ros2 -f docker/docker-compose.yml build

镜像名:ros2-humble-dev:latest,约 3GB。

2.3 镜像内已装

  • ROS2 Humble Desktop
  • colcon-common-extensions + colcon-argcomplete
  • cv_bridge (openCV ↔ ROS Image)
  • ros-humble-tf2-tools (view_frames)
  • ros-humble-robot-state-publisher (URDF → TF)

未装(按需补):

  • ros-humble-rmw-cyclonedds-cpp(默认 fastdds 够用)
  • ros-humble-ros2-control
  • ros-humble-moveit
  • ros-humble-navigation2

2.4 修改镜像(自定义)

加包:在 apt-get install 加一行:

RUN apt-get install -y ros-humble-ros2-control ros-humble-ros2-controllers

加 Python 包:

RUN pip3 install ultralytics==8.0.0 numpy==1.26

3. 容器编排

3.1 docker-compose.yml

docker/docker-compose.yml:

name: ros2                     # 独立 compose project(脱离默认 docker 分组)

services:
  ros2:
    build: .
    image: ros2-humble-dev:latest
    container_name: ros2_dev

    privileged: true           # 调试用
    stdin_open: true           # docker exec -it
    tty: true

    networks:                  # 自定义 bridge(脱离 docker_default)
      ros2_net:
        ipv4_address: 172.20.0.10   # 固定 IP,便于 ROS_STATIC_PEERS

    environment:
      - ROS_DOMAIN_ID=0
      # 不要设 RMW_IMPLEMENTATION=rmw_cyclonedds_cpp:
      # 镜像没装 cyclone dds,CMake 配置会失败。
      - RCUTILS_COLORIZED_OUTPUT=1

    volumes:
      - ..:/root/ros2_ws        # bind mount 本机 D:\xs\ros2

    working_dir: /root/ros2_ws

    command: ["bash", "-lc", "tail -f /dev/null"]   # 容器永不退

networks:
  ros2_net:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/24
          gateway: 172.20.0.1

3.2 为什么自定义 bridge 而不是 host network

ROS2 默认用 DDS multicast 在同一网段自动发现节点。 默认 docker bridge 网络会拦截 multicast,导致容器内节点看不见彼此。

本仓库选择自定义 bridge(ros2_net,子网 172.20.0.0/24),原因:

  • 跟系统 docker_default 隔离,不让无关容器"窜"进 ROS 节点组
  • 容器固定 IP(172.20.0.10),便于 ROS_STATIC_PEERS 配置
  • bridge 内 multicast 在同一 docker 网络内能正常通——本仓库默认 fastdds + 单机场景下,所有节点都在 ros2_dev 容器里,bridge 完全够用

如果做跨主机 ROS2 部署(PC ↔ RDK X5 ↔ RK3506,见 100-embedded-deployment.md),需要 network_mode: host 或 host gateway。

3.3 为什么 bind mount 整个工程

.. 是 docker-compose.yml 的上一级(D:\xs\ros2)。挂到容器内 /root/ros2_ws,你在 Windows 改代码,容器内 colcon 立即看到(--symlink-install)。


4. 容器生命周期命令

# 构建镜像
docker compose -p ros2 -f D:\xs\ros2\docker\docker-compose.yml build

# 启动(后台)
docker compose -p ros2 -f D:\xs\ros2\docker\docker-compose.yml up -d

# 状态
docker compose -p ros2 -f D:\xs\ros2\docker\docker-compose.yml ps

# 进开发终端(必须先 source ROS2 + 本项目 install)
docker exec -it ros2_dev bash -lc "source /opt/ros/humble/setup.bash && source /root/ros2_ws/install/setup.bash && exec bash"

# 一次性跑命令
docker exec ros2_dev bash -lc "cd /root/ros2_ws && colcon build --packages-select py_pubsub"

# 关
docker compose -p ros2 -f D:\xs\ros2\docker\docker-compose.yml down

# 重启
docker compose -p ros2 -f D:\xs\ros2\docker\docker-compose.yml restart

# 删容器(保留镜像)
docker compose -p ros2 -f D:\xs\ros2\docker\docker-compose.yml down

# 删镜像
docker rmi ros2-humble-dev:latest

# 看日志
docker logs -f ros2_dev

5. 一键启动脚本

本仓库的所有"一键"命令都在 scripts/ 目录下,没有项目根的 start.ps1 / start.sh / build.sh(老文档里残留的引用一律作废,统一指向 scripts/)。

5.1 进入开发终端(交互式 shell)

bash scripts/shell.sh

等价于:

  • docker ps 看容器是否在跑
  • 如果没跑 → 自动 docker run -d -it ... ros2-humble-dev:latest bash 启起来
  • docker exec -it ros2_dev bash -lc "source /opt/ros/humble/setup.bash && source /root/ros2_ws/install/setup.bash && cd /root/ros2_ws && exec bash"

5.2 编译 12 个包(容器内)

bash scripts/build.sh

等价于:

source /opt/ros/humble/setup.bash
cd /root/ros2_ws
colcon build --symlink-install --executor sequential \
  --packages-select <12 个包>

--executor sequential 必需。colcon 默认 parallel,12 个包并行构建 时 cpp_custom_interface 的 rosidl export cmake 会偶发 CMake 报错。 串行构建 100% 稳定。详见 doc/80-package-build.md

5.3 跑所有测试

bash scripts/test.sh

等价于 colcon test --executor sequential --packages-select <12 个包> + colcon test-result --all

5.4 跑 launch demo

bash scripts/launch.sh pubsub_launch 30     # 跑 30 秒自动停
bash scripts/launch.sh full_demo_launch -1  # -1 = 一直跑(后台)

5.5 清理构建产物

bash scripts/clean.sh   # 等价于 rm -rf build install log

6. 调试技巧

6.1 看容器日志

docker logs ros2_dev
docker logs -f ros2_dev       # 持续

6.2 进容器交互 shell

docker exec -it ros2_dev bash
# 进入后:
source /opt/ros/humble/setup.bash
cd /root/ros2_ws
source install/setup.bash

6.3 在容器内单次跑命令

docker exec ros2_dev bash -lc "source /opt/ros/humble/setup.bash && ros2 node list"

6.4 看 DDS 流量

docker exec ros2_dev bash -lc "source /opt/ros/humble/setup.bash && ros2 doctor --report"

6.5 看网络

docker exec ros2_dev bash -lc "ip addr; ip route"

6.6 容器与宿主机共享 GPU(可选)

services:
  ros2:
    deploy:
      resources:
        reservations:
          devices:
            - driver: nvidia
              count: 1
              capabilities: [gpu]

7. 常见坑

7.1 容器启动后找不到 ros2 命令

容器里 /opt/ros/humble/setup.bash 没 source。每个 shell 都要 source, 或者写进 ~/.bashrc(已加,新 bash 自动 source)。

7.2 改了源码但 colcon 看不到

确认 --symlink-install(默认配置里加上了)。否则需要重 build。

7.3 跨容器看不到节点

  • 同一 ROS Domain(ROS_DOMAIN_ID)
  • host network(本仓库用了)
  • multicast 没被拦截

7.4 Windows bind mount 文件锁

有时 LSP / IDE 持文件锁,导致容器内 colcon 失败。关掉 IDE 或在容器内编辑。

7.5 容器启动很慢

  • Docker Desktop 未运行
  • WSL2 后端未启用
  • 镜像太大(本仓库 ~3GB 正常)

7.6 容器 OOM

Docker Desktop → Settings → Resources → Memory 调到 ≥ 4GB。


8. 多机 / 多机器人扩展

# docker-compose.yml 改成:
services:
  robot1:
    image: ros2-humble-dev:latest
    container_name: ros2_robot1
    network_mode: host
    environment:
      - ROS_DOMAIN_ID=42
      - ROS_NAMESPACE=robot1
    volumes:
      - ./robot1_conf:/root/ros2_ws

  robot2:
    image: ros2-humble-dev:latest
    container_name: ros2_robot2
    network_mode: host
    environment:
      - ROS_DOMAIN_ID=42
      - ROS_NAMESPACE=robot2
    volumes:
      - ./robot2_conf:/root/ros2_ws

  central:
    image: ros2-humble-dev:latest
    container_name: ros2_central
    network_mode: host
    environment:
      - ROS_DOMAIN_ID=42
    command: ["bash", "-lc", "ros2 launch bringup multi_robot_launch.py"]

每个 container 各跑一组节点,ROS_NAMESPACE 隔离命名空间, ROS_DOMAIN_ID 共享同一总线 → 跨容器通讯。

详见 doc/100-embedded-deployment.md


9. 在本仓库里跑

9.1 一键启(推荐用 Makefile)

make build          # 首次构建镜像
make up             # 后台启动容器
make shell          # 进入开发终端(自动 source ROS2 + install)
make colcon-build   # 编译 12 包
make colcon-test    # 跑 82 测试
make full-demo      # 跑 11 节点 full_demo

9.2 进入后跑测试

bash scripts/test.sh   # 推荐:自带 --executor sequential

9.3 跑 demo

docker exec ros2_dev bash -lc "source /opt/ros/humble/setup.bash && source /root/ros2_ws/install/setup.bash && ros2 launch bringup full_demo_launch.py"

10. 进阶:多阶段构建 + 镜像瘦身

10.1 当前镜像大小

docker images ros2-humble-dev
# SIZE: 3.4GB

来源:

  • osrf/ros:humble-desktop: ~2.1GB(包含 RViz / rqt / Gazebo)
  • 我们的 apt 包 + colcon: ~1.3GB

10.2 改用 osrf/ros:humble-ros-base

基础镜像改成 humble-ros-base(无 RViz / rqt):

FROM osrf/ros:humble-ros-base

SIZE 减少 ~1.5GB。但少了 RViz / rqt / Gazebo,如果需要这些再加 apt。

10.3 多阶段构建(进一步瘦身)

# Stage 1: build
FROM osrf/ros:humble-ros-base AS builder
# ... 装 build 工具,build 我们的包 ...

# Stage 2: runtime
FROM osrf/ros:humble-ros-base
COPY --from=builder /root/ros2_ws/install /root/ros2_ws/install
# 不带 build 工具,更小

适合 CI 流水线 + 生产环境。


接下来读

主题 文档
venv 工作流 02-virtualenv.md
测试策略 90-testing.md
三机部署 100-embedded-deployment.md
项目总览 00-overview.md


📖 阅读路径导航

💡 这是仓库 doc/ 下所有文档的推荐阅读顺序。返回 README 总导航

本文预计阅读时间: 40 分钟 📍 当前位置: 第 20 / 24 篇