Docker入门——机器人开发环境的隔离与复现
面试翻车现场
面试过一个候选人,我问他:"你们团队开发环境怎么管理的?新人入职怎么配环境?"
他说:"每个人自己装Ubuntu、ROS2、各种依赖,遇到问题互相帮忙解决。"
我问:"如果两个人用了不同版本的库,代码在一个人电脑上能跑,另一个人跑不了呢?"
他说:"那就……统一版本?"
这就是"在我电脑上能跑"的经典问题。机器人开发依赖复杂——ROS2版本、Python版本、各种C++库,每个人环境不一样,出了问题很难排查。Docker可以解决这个问题:把整个开发环境打包成镜像,任何人拉下来就能用,环境完全一致。
Docker是什么
Docker是容器化平台。简单说,它把应用程序和所有依赖打包在一起,形成一个独立的运行环境(容器)。容器之间互相隔离,和宿主机也隔离。
虚拟机vs容器:虚拟机模拟整个硬件,运行完整的操作系统,启动慢、资源占用大;容器共享宿主机内核,只隔离文件系统、进程、网络等,启动快、资源占用小。
安装Docker
Ubuntu上安装Docker:
# 卸载旧版本
sudo apt remove docker docker-engine docker.io containerd runc
# 设置仓库
sudo apt update
sudo apt install -y ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 安装Docker
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
# 把当前用户加入docker组(免sudo)
sudo usermod -aG docker $USER
重新登录后生效。测试安装:
docker run hello-world
基本命令
镜像操作:
docker pull ubuntu:22.04 # 下载镜像
docker images # 列出本地镜像
docker rmi ubuntu:22.04 # 删除镜像
docker build -t myimage . # 从Dockerfile构建镜像
容器操作:
docker run -it ubuntu:22.04 bash # 运行容器,交互式终端
docker ps # 列出运行中的容器
docker ps -a # 列出所有容器(包括已停止的)
docker stop <container_id> # 停止容器
docker start <container_id> # 启动已停止的容器
docker rm <container_id> # 删除容器
docker exec -it <container_id> bash # 进入运行中的容器
-it是交互模式,bash是启动后执行的命令。运行后你就进入了容器的bash。
Dockerfile:定义镜像
Dockerfile是一个文本文件,描述了如何构建镜像。
# 基础镜像
FROM ubuntu:22.04
# 设置环境变量
ENV DEBIAN_FRONTEND=noninteractive
# 安装依赖
RUN apt update && apt install -y \
ros-humble-desktop \
python3-colcon-common-extensions \
&& rm -rf /var/lib/apt/lists/*
# 设置工作目录
WORKDIR /robot_ws
# 复制代码
COPY . .
# 编译
RUN /bin/bash -c "source /opt/ros/humble/setup.bash && colcon build"
# 启动命令
CMD ["/bin/bash"]
构建镜像:
docker build -t robot-dev:v1 .
运行容器:
docker run -it robot-dev:v1 bash
数据卷:持久化数据
容器删除后,里面的数据就没了。用数据卷(volume)可以把宿主机的目录映射到容器里,数据持久化。
# 挂载目录
docker run -it -v /home/robot/robot_ws:/robot_ws robot-dev:v1 bash
# 挂载多个目录
docker run -it \
-v /home/robot/robot_ws:/robot_ws \
-v /home/robot/data:/data \
robot-dev:v1 bash
这样容器里的/robot_ws就是宿主机的/home/robot/robot_ws,修改会同步。
和机器人开发的关系
Docker在机器人开发中非常有用:
环境一致性:团队共享同一个镜像,所有人开发环境完全一样。新人入职,拉镜像就能开始开发,不用花三天装环境。
环境隔离:不同项目用不同镜像,依赖不冲突。项目A用ROS2 Humble,项目B用ROS2 Iron,互不影响。
快速部署:开发环境打包成镜像,部署到机器人上也是同一个镜像,避免"在我电脑上能跑"的问题。
CI/CD集成:自动化测试在容器里运行,每次代码提交都在干净环境里测试,结果可复现。
面试常见考点
"Docker和虚拟机有什么区别?"——虚拟机模拟硬件,运行完整操作系统,启动慢、资源占用大;容器共享宿主机内核,启动快、资源占用小。容器更适合应用部署,虚拟机适合需要完全隔离的场景。
"Dockerfile里FROM、RUN、CMD的区别?"——FROM指定基础镜像;RUN在构建时执行命令,结果会保存到镜像层;CMD在容器启动时执行,可以被覆盖。
"怎么把宿主机的文件传到容器里?"——用-v挂载目录,或者用docker cp命令复制文件。
"容器删除后数据还在吗?"——容器本身的数据会丢失。用数据卷(volume)或绑定挂载(bind mount)可以持久化数据。
Docker网络与ROS2
Docker默认用bridge网络,容器有独立的IP地址。如果你需要在容器里运行ROS2节点并和外部通信,需要用host网络模式:docker run --net=host。这样容器直接使用宿主机的网络栈,DDS的multicast发现机制才能正常工作。否则容器内的ROS2节点无法被外部发现,这是很多新手用Docker跑ROS2时踩的第一个坑。
Docker在机器人开发中的应用
Docker在机器人项目中最大的价值是环境隔离和可复现性。想象一下:团队里每个人开发环境不同,在我电脑上能跑的问题层出不穷。用Docker可以把ROS2版本、依赖库、编译工具链全部打包成镜像,任何人拉取镜像就能得到完全一致的环境。实际使用中,通常会把编译环境和运行环境分开,用多阶段构建减小最终镜像体积。
另外,Docker镜像的层缓存机制也值得了解。Dockerfile中把不常变化的指令放前面(比如安装系统依赖),频繁变化的放后面(比如拷贝源码),这样可以充分利用缓存加速构建。
给你的建议
Docker是现代软件开发的标配,机器人开发也应该用起来。
先从简单的开始:用现成的ROS2镜像(osrf/ros:humble-desktop-full),在容器里开发。熟悉后再自己写Dockerfile。
团队共享一个基础镜像,所有人用同样的环境。新人入职,一条命令拉镜像,马上开始开发。
遇到依赖冲突、环境问题的,试试Docker。把环境打包成镜像,问题就消失了。
下一篇会讲Docker进阶——多容器编排和机器人仿真环境搭建。
上一篇:第95篇 SSH远程开发——连接机器人本体调试的标配方式
下一篇预告:第97篇 Docker进阶——多容器编排和机器人仿真环境搭建
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)