三分钟快速了解Docker

Docker 是什么?

Docker 就是一个**"轻量级的虚拟机"**,但它比虚拟机更聪明。它把操作系统、代码库、依赖包全都打包在一起。

① 镜像 (Image) ------ "游戏光盘"
  • 是什么: 这是一个只读的模板。你的导师把配置好的环境(Ubuntu + ROS 2 + Autoware 依赖)打包成了一个文件,这就叫镜像。

  • 特点: 它是冰冻的,怎么玩都不会坏。

  • 你的操作: 就像你买了一张《黑神话:悟空》的光盘,所有人买到的光盘内容都是一模一样的。

② 容器 (Container) ------ "游戏存档 / 运行中的游戏"
  • 是什么: 当你把"镜像"运行起来,它就变成了"容器"。这就是你现在终端里看到的 root@21f8611da6f8 这个环境。

  • 特点: 它是一次性的、临时的。 你在里面安装软件、编译代码,都是在当前的"存档"里操作。

  • 关键点: 如果你把容器删了(docker rm),你在里面装的软件、改的系统配置,就全部消失了,就像没保存游戏直接关机一样。

③ 挂载 (Volume) ------ "连接现实世界的传送门" 🌟🌟🌟
  • 作用: 因为容器里存不住东西,我们需要把容器里的某个文件夹,打通到你真实电脑(WSL)的硬盘上。

  • 你的现状:

    • 你的代码其实是在 WSL(真实世界)里的。

    • Docker 只是负责提供一个编译环境(编译器、ROS 工具)。

    • 它俩通过 -v 命令连在了一起。


3. 图解:你现在的套娃结构

为了让你更清楚,咱们再理一下这个层级(从外到内):

  1. Windows 11: 你的物理电脑(房东)。

  2. WSL 2 (Ubuntu): 寄生在 Windows 上的 Linux 系统(你的出租屋)。你的代码文件存在这里!

  3. Docker 引擎: 运行在 WSL 里的管家。

  4. 容器 (Autoware 环境): 管家临时搭的一个帐篷。你进去编译代码,编译完你就出来了。

4. 为什么要这样设计?(好处)

这种架构有巨大的优势:

  1. 统一标准: 不管你是用 Windows 还是 Mac,只要跑这个 Docker 镜像,大家的代码运行环境是像素级一致的。不会出现"由于系统版本不同导致的 Bug"。

  2. 甚至车端一致: 你在电脑 Docker 里跑的代码,最后部署到真实的自动驾驶汽车上时,车上的电脑里跑的也是同一个 Docker 镜像。这叫"端到端一致性"。

  3. 不怕搞坏:

    • 如果你把 Docker 容器里的系统搞崩了(比如误删了 /usr/bin),没关系。

    • exit 退出,docker rm 删掉容器。

    • 重新 docker run,瞬间又变回了一个全新的、干净的环境。

    • 前提是:你别把挂载的代码文件夹给删了!

5. 总结:实习生的 Docker 生存法则

  • Docker 是你的"编译车间": 你进去只是为了利用里面的工具(gcc, colcon, ros2)来干活。

  • 代码在"外面": 你的核心资产(代码)是通过挂载放进去的。

  • 别太把容器当回事: 容器是消耗品,坏了就换。

  • 千万把挂载当回事: 那个连接内外的"传送门"文件夹,是你的命根子。


误删容器了怎么办:

我们来拆解一下,如果现在你的容器突然没了(或者被你误删了),会发生什么:

1. 需要重新下载几个 G 的系统吗?

不需要。

  • 还记得我们说的"游戏光盘"(镜像 Image)吗?

  • Docker 镜像 是存储在你的硬盘深处的,删除容器 (存档)并不会删除镜像(光盘)。

  • 你重新敲一行启动命令(docker run ...),只需要 1秒钟,一个新的容器就会根据那个镜像立刻弹出来。它不需要联网下载任何东西。

2. 需要重新编译代码吗?

大概率不需要。 😲

  • 这得益于你的挂载(Volume Mapping)

  • 请回忆一下,你编译生成的 buildinstall 文件夹在哪里?它们是在 ~/work_space/lubo_auto_car 目录下。

  • 而这个目录,是通过"传送门"直接连接到你的 WSL(一楼) 的。

  • 结论: 容器虽然炸了,但它死前编译好的 buildinstall 文件夹还安安全全地躺在你的 WSL 硬盘里。

  • 恢复: 新容器启动后,它再次连接到这个文件夹,看到现成的 install 文件夹,你只需要 source install/setup.bash,马上就能跑,甚至不用重新编译。

3. 那真正的"麻烦"在哪里?

你担心的"麻烦"主要来自这里------你在容器里的"临时装修"会丢失。

举个例子,如果你在上一台容器里为了调试代码,手动干了这些事:

  • apt install vim (装了个编辑器)

  • pip install some-library (装了个 Python 库)

  • export ROS_DOMAIN_ID=30 (设了个环境变量,且没写进配置文件)

一旦容器删了,这些东西就真没了。

新启动的容器,是一个**"恢复出厂设置"**的状态(基于原始镜像)。你需要重新手动敲一遍这些安装命令。


💡 总结:两个灾难的对比

灾难类型 误删挂载的文件夹 (上次的事故) 误删 Docker 容器 (你现在的担心)
性质 物理毁灭 重启还原
代码会丢吗? 会,找不回就是永别 不会,代码在外面
编译结果会丢吗? 不会,也在外面
环境会丢吗? 不会 (临时装的软件要重装)
恢复时间 几小时 ~ 几天 几分钟
心情 😭 (想离职) 😑 (啧,真麻烦)

⚡️ 给实习生的建议

不要在容器里"偷偷"装软件。

如果你发现代码运行缺了一个库(比如 scipy),不要 只在终端里敲 pip install scipy 就算了。

一定要告诉你的导师 ,让他把这个库加到Dockerfile(镜像的配方表)里去,或者写在项目的依赖文档里。这样下次大家启动新容器时,环境就是自带这个库的了。


常用的Docker命令:


第一类:镜像操作 💿

这些命令是在操作那些只读的系统模板

  1. 查看我有多少张光盘

    复制代码
    docker images
    • 作用: 列出本地下载好的所有镜像。

    • 关注点: REPOSITORY (名字), TAG (版本), IMAGE ID (身份证号), SIZE (大小)。

  2. 去公司网盘或者网上下载镜像

    复制代码
    docker pull <镜像名>:<版本号>
    # 例子:docker pull osrf/ros:humble-desktop
    • 作用: 从网上下载镜像。如果没写版本号,默认下载最新版 (latest)。
  3. 删除镜像 ⚠️

    复制代码
    docker rmi <镜像ID 或 镜像名>
    # rmi = remove image
    • 注意: 如果有容器(存档)正在使用这张光盘,你是删不掉的。你需要先删容器,再删镜像。

第二类:容器操作 (玩游戏/读档) 📦

这是你每天工作频率最高的命令。

  1. 看看现在谁在运行

    复制代码
    docker ps
    • 作用: 列出所有正在运行的容器(活着的)。

    • 重要信息: CONTAINER ID (短ID), NAMES (你起的名字,比如 vigilant_newton)。

  2. 看看所有存档 (包括死掉的) 🌟

    复制代码
    docker ps -a
    • 作用: 非常重要! 很多时候你以为容器丢了,其实它只是停止运行了(Stopped)。加了 -a (all) 才能看到它们。
  3. 启动/停止 容器

    复制代码
    docker start <容器名>   # 启动一个停止的容器
    docker stop <容器名>    #以此停止一个运行的容器
  4. 进入容器内部 🌟🌟🌟 这是你每天都要用的命令,用来进入那个"黑框框"编译代码。

    复制代码
    docker exec -it <容器名> bash
    • 拆解:

      • exec: 执行命令。

      • -it: i nteractive (交互式) + tty (终端)。人话:给我一个能打字的终端。

      • bash: 我要用的具体程序(Linux 的命令行外壳)。


第三类:创建与毁灭容器🔨

  1. 新建一个存档 (从镜像启动容器) 🌟🌟🌟 这是最长、最复杂,但也最重要的命令。

    复制代码
    docker run -it -d --name <起个名字> -v <宿主机路径>:<容器内路径> <镜像名>
    • -d: 后台运行(Detached)。不然你一关终端,容器就挂了。

    • --name : 给容器起个好记的名字(比如 my_autoware),不然它会随机叫 happy_einstein 之类的。

    • -v : 挂载(传送门)! 也就是你之前栽跟头的地方。把本地代码连进去。

    • 例子:

      复制代码
      docker run -it -d --name my_car -v ~/work_space:/root/work_space autoware/universe:latest
  2. 删档 (删除容器) ⚠️

    复制代码
    docker rm <容器名>
    • 注意: 只能删停止状态 的容器。如果要强制删正在跑的,加 -f (force):docker rm -f <容器名>

    • 再次提醒: 删了容器,里面临时装的软件(vim, ping)就没了,但挂载的代码(WSL里)不会丢


案例解释:

1. 本地加载已有镜像 (Load Image)

复制代码
sudo docker load -i *.tar
  • 含义: 这是一个"离线安装"步骤。

  • 作用: 如果你的公司内网不能随便下载 10GB 的镜像,或者导师直接用 U 盘拷给你一个打包好的镜像文件(.tar 格式),你就用这个命令把它解压并导入到你的本地 Docker 仓库里。


2. 本地配置 (Display Configuration)

这一大段全是为了一件事:让 Docker 能"投屏"到你的屏幕上。

因为 Docker 本质上是一个没有屏幕的后台进程,如果你想看 Rviz,就必须打通它和宿主机(你的电脑)之间的图形显示通道。

  • xhost +local:root

    • 这是一个"暴力"授权命令。意思是:允许本地的 root 用户(也就是 Docker 容器里的默认用户)访问我的屏幕。
  • XAUTH=/tmp/.docker.xauth ... xauth nlist ...

    • 这是更高级、更安全的做法。

    • 它创建了一个"通行证"文件(.docker.xauth)。

    • 它把你当前电脑的显示授权信息(Magic Cookie)复制到这个文件里。

    • 目的: 稍后我们会把这个文件挂载进容器,容器拿着这个"通行证",才被允许在你的屏幕上画图。


3. 启动容器 (Run Container) ------ 最关键的一步

这行命令非常长,我们把它的参数拆开看,每个都很重要:
Bash

复制代码
sudo docker run -it --gpus all \
  --name autoware \
  --env="DISPLAY=$DISPLAY" \
  --env="QT_X11_NO_MITSHM=1" \
  --env="XAUTHORITY=/tmp/.docker.xauth" \
  -v /tmp/.X11-unix:/tmp/.X11-unix:rw \
  -v /tmp/.docker.xauth:/tmp/.docker.xauth \
  -v /etc/localtime:/etc/localtime:ro \
  -v /home/y/work_space:/root/work_space \  # <--- 重点关注这行
  autoware_image:gpu
  • --gpus all开启显卡加速。没有这句,你的深度学习模型跑不动,Rviz 也会卡成 PPT。

  • --env="DISPLAY=$DISPLAY":告诉容器:"屏幕的地址在这里"。

  • --env="QT_X11_NO_MITSHM=1"防闪退补丁。这是为了解决 Qt 程序的共享内存 Bug,不加这句,Rviz 打开瞬间就会崩。

  • -v /tmp/.X11-unix:/tmp/.X11-unix:rw挂载图形接口。这是物理上的显示插口,必须挂载。

  • -v /tmp/.docker.xauth:/tmp/.docker.xauth挂载通行证。把刚才第2步生成的"通行证"塞进容器。

  • -v /home/y/work_space:/root/work_space🚨 高能预警!

    • 这是你需要手动修改的地方!

    • /home/y/work_space别人电脑上的路径。

    • 你需要把它改成你自己的 WSL 路径,比如:~/autoware_ws/wordk_space

    • 如果不改,Docker 启动后里面是空的,或者直接报错路径不存在。


4. 启动仿真 demo

复制代码
ros2 launch autoware_launch planning_simulator.launch.xml ...
  • 含义: 这是容器启动成功并进入终端后,运行的第一条命令。

  • 作用: 启动 Autoware 的规划仿真器。如果前面第 2、3 步配置正确,此时你的屏幕上应该会弹出一个 Rviz 窗口,显示出地图和小车。

总结

这段脚本是 "带显卡 + 带显示器" 的 Docker 标准启动模板。

你需要注意的唯一修改点是: 仔细检查第 3 步里 -v 挂载代码的那一行,确保冒号左边的路径是你自己电脑上真实的路径!

相关推荐
Genie cloud4 小时前
在 Mac 上使用 Docker 安装宝塔并部署 LNMP 环境
macos·docker·容器·云计算
2501_944525544 小时前
Flutter for OpenHarmony 个人理财管理App实战 - 预算详情页面
android·开发语言·前端·javascript·flutter·ecmascript
i建模4 小时前
在 Rocky Linux 上安装轻量级的 XFCE 桌面
linux·运维·服务器
zhuqiyua4 小时前
第一次课程家庭作业
c++
Data_Journal4 小时前
Scrapy vs. Crawlee —— 哪个更好?!
运维·人工智能·爬虫·媒体·社媒营销
4 小时前
java关于内部类
java·开发语言
好好沉淀4 小时前
Java 项目中的 .idea 与 target 文件夹
java·开发语言·intellij-idea
只是懒得想了4 小时前
C++实现密码破解工具:从MD5暴力破解到现代哈希安全实践
c++·算法·安全·哈希算法
lsx2024064 小时前
FastAPI 交互式 API 文档
开发语言
VCR__5 小时前
python第三次作业
开发语言·python