# 85 · Docker 容器化开发(完全指南) > **目标**:吃透本仓库 Docker 配置,知道每行在做什么,能改能扩,能在 Win/macOS/Linux 一致跑 ROS2。 --- ## 目录 - [1. 为什么用 Docker](#1-为什么用-docker) - [2. 镜像构建](#2-镜像构建) - [3. 容器编排](#3-容器编排) - [4. 容器生命周期命令](#4-容器生命周期命令) - [5. 一键启动脚本](#5-一键启动脚本) - [6. 调试技巧](#6-调试技巧) - [7. 常见坑](#7-常见坑) - [8. 多机 / 多机器人扩展](#8-多机--多机器人扩展) - [9. 在本仓库里跑](#9-在本仓库里跑) - [10. 进阶:多阶段构建 + 镜像瘦身](#10-进阶多阶段构建--镜像瘦身) --- ## 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/Dockerfile`](../docker/Dockerfile) 在 `osrf/ros:humble-desktop` 之上加: ```dockerfile 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 构建 ```powershell # Windows docker compose -f D:\xs\ros2\docker\docker-compose.yml build ``` ```bash # Linux docker compose -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` 加一行: ```dockerfile RUN apt-get install -y ros-humble-ros2-control ros-humble-ros2-controllers ``` 加 Python 包: ```dockerfile RUN pip3 install ultralytics==8.0.0 numpy==1.26 ``` --- ## 3. 容器编排 ### 3.1 docker-compose.yml [`docker/docker-compose.yml`](../docker/docker-compose.yml): ```yaml services: ros2: build: . image: ros2-humble-dev:latest container_name: ros2_dev privileged: true # 调试用 stdin_open: true # docker exec -it tty: true network_mode: host # DDS multicast 必须 environment: - ROS_DOMAIN_ID=0 # 不要设 RMW_IMPLEMENTATION=rmw_cyclonedds_cpp: # 镜像没装 cyclone dds,CMake 配置会失败。 volumes: - ..:/root/ros2_ws # bind mount 本机 D:\xs\ros2 working_dir: /root/ros2_ws command: ["bash", "-lc", "tail -f /dev/null"] # 容器永不退 ``` ### 3.2 为什么 host network ROS2 默认用 DDS multicast 在同一网段自动发现节点。多容器或跨主机时,**bridge 网络 会拦截 multicast**,导致节点看不见彼此。 `network_mode: host` 让容器用宿主机的网络栈,直接走 multicast。 ### 3.3 为什么 bind mount 整个工程 `..` 是 docker-compose.yml 的上一级(`D:\xs\ros2`)。挂到容器内 `/root/ros2_ws`,**你在 Windows 改代码,容器内 colcon 立即看到**(`--symlink-install`)。 --- ## 4. 容器生命周期命令 ```powershell # 构建镜像 docker compose -f D:\xs\ros2\docker\docker-compose.yml build # 启动(后台) docker compose -f D:\xs\ros2\docker\docker-compose.yml up -d # 状态 docker compose -f D:\xs\ros2\docker\docker-compose.yml ps # 进开发终端 docker exec -it ros2_dev bash -lc "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 -f D:\xs\ros2\docker\docker-compose.yml down # 重启 docker compose -f D:\xs\ros2\docker\docker-compose.yml restart # 删容器(保留镜像) docker compose -f D:\xs\ros2\docker\docker-compose.yml down # 删镜像 docker rmi ros2-humble-dev:latest # 看日志 docker logs -f ros2_dev ``` --- ## 5. 一键启动脚本 ### 5.1 start.ps1 (Windows) ```powershell powershell D:\xs\ros2\start.ps1 ``` 等价于: ```powershell docker compose build # 首次 5-10min docker compose up -d docker exec ros2_dev bash -lc "cd /root/ros2_ws && bash build.sh" docker exec -it ros2_dev bash -lc "source install/setup.bash && exec bash" ``` ### 5.2 start.sh (Linux/macOS) ```bash ./start.sh ``` ### 5.3 build.sh (容器内) ```bash bash build.sh # 1) source /opt/ros/humble/setup.bash # 2) colcon build --symlink-install --packages-select # 3) ls install/ # 4) 打印运行命令速查 ``` --- ## 6. 调试技巧 ### 6.1 看容器日志 ```bash docker logs ros2_dev docker logs -f ros2_dev # 持续 ``` ### 6.2 进容器交互 shell ```bash docker exec -it ros2_dev bash # 进入后: source /opt/ros/humble/setup.bash cd /root/ros2_ws source install/setup.bash ``` ### 6.3 在容器内单次跑命令 ```bash docker exec ros2_dev bash -lc "source /opt/ros/humble/setup.bash && ros2 node list" ``` ### 6.4 看 DDS 流量 ```bash docker exec ros2_dev bash -lc "source /opt/ros/humble/setup.bash && ros2 doctor --report" ``` ### 6.5 看网络 ```bash docker exec ros2_dev bash -lc "ip addr; ip route" ``` ### 6.6 容器与宿主机共享 GPU(可选) ```yaml 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. 多机 / 多机器人扩展 ```yaml # 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`](100-embedded-deployment.md)。 --- ## 9. 在本仓库里跑 ### 9.1 一键启 ```powershell powershell D:\xs\ros2\start.ps1 ``` ### 9.2 进入后跑测试 ```bash docker exec ros2_dev bash -lc "source /opt/ros/humble/setup.bash && cd /root/ros2_ws && colcon test --packages-select py_pubsub cpp_pubsub py_srv py_action_demo cpp_robot_tf2 py_vision_demo bringup" ``` ### 9.3 跑 demo ```bash docker exec ros2_dev bash -lc "source /root/ros2_ws/install/setup.bash && ros2 launch bringup full_demo_launch.py" ``` --- ## 10. 进阶:多阶段构建 + 镜像瘦身 ### 10.1 当前镜像大小 ```bash 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): ```dockerfile FROM osrf/ros:humble-ros-base ``` **SIZE 减少 ~1.5GB**。但少了 RViz / rqt / Gazebo,如果需要这些再加 apt。 ### 10.3 多阶段构建(进一步瘦身) ```dockerfile # 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`](02-virtualenv.md) | | 测试策略 | [`90-testing.md`](90-testing.md) | | 三机部署 | [`100-embedded-deployment.md`](100-embedded-deployment.md) | | 项目总览 | [`00-overview.md`](00-overview.md) | --- --- ## 📖 阅读路径导航 > 💡 这是仓库 `doc/` 下所有文档的推荐阅读顺序。[返回 README 总导航](../README.md#-23-篇文档怎么读) > > ⏱ **本文预计阅读时间**: 40 分钟 > 📍 **当前位置**: 第 20 / 24 篇 - ⏮ **上一篇**: [colcon / ament 包构建](80-package-build.md) - ⏭ **下一篇**: [测试金字塔](90-testing.md)