参考博客:https://www.helywin.com/posts/20260605124741/

当前完成状态

  • 容器名:ros-melodic-box
  • 容器 home:~/distrobox-homes/ros-melodic
  • 系统:Ubuntu 18.04.6 LTS / amd64
  • ROS:ros-melodic-desktop-full 1.4.1-0bionic.20230620.175308
  • 默认 shell:bash
  • 图形加速:RTX 5070 Ti Laptop GPU,宿主 NVIDIA 610.43.02 驱动

核心原则

  • 所有镜像源使用华为云加速(Ubuntu apt、ROS apt、Docker 容器镜像)
  • 包管理只用 apt,不使用 rosdep
  • 使用 Podman + Distrobox 运行 rootless Ubuntu 18.04 容器
  • 不升级 Ubuntu 18.04 的 Mesa/glibc,通过 Distrobox 复用宿主 NVIDIA 驱动

一、宿主机准备(EndeavourOS)

1.1 安装 Podman 和 Distrobox

EndeavourOS(Arch 系)使用 pacman 安装:

BASH
sudo pacman -S --needed podman distrobox

验证:

BASH
podman --version
distrobox --version

1.2 验证宿主机 NVIDIA PRIME offload

本文使用的机器是 Intel Arrow Lake 核显 + NVIDIA 独显的混合显卡环境。先在宿主机确认独显和 PRIME offload 正常:

BASH
nvidia-smi --query-gpu=name,driver_version --format=csv,noheader

__NV_PRIME_RENDER_OFFLOAD=1 \
__GLX_VENDOR_LIBRARY_NAME=nvidia \
glxinfo -B

当前宿主机输出为 NVIDIA GeForce RTX 5070 Ti Laptop GPU, 610.43.02

1.3 用户组配置(串口/摄像头权限,可选)

如果需要使用串口或摄像头,在宿主机执行:

BASH
sudo usermod -aG dialout $USER   # 串口权限
sudo usermod -aG video $USER     # 摄像头/GPU 权限

添加组后需要 完全注销并重新登录 才能生效。

二、创建 Ubuntu 18.04 容器

2.1 使用华为云镜像拉取 Ubuntu 18.04

华为云 SWR 提供 Docker Hub 镜像加速:

BASH
podman pull swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/library/ubuntu:18.04
podman tag swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/library/ubuntu:18.04 ubuntu:18.04

2.2 创建 Distrobox 容器

BASH
distrobox create \
  --image ubuntu:18.04 \
  --name ros-melodic-box \
  --home ~/distrobox-homes/ros-melodic \
  --nvidia \
  --additional-flags "--env SHELL=/bin/bash --env __NV_PRIME_RENDER_OFFLOAD=1 --env __GLX_VENDOR_LIBRARY_NAME=nvidia --env __VK_LAYER_NV_optimus=NVIDIA_only" \
  --yes

这里显式设置 SHELL=/bin/bash,是因为 Ubuntu 18.04 镜像没有安装 zsh。如果直接继承 EndeavourOS 宿主机的 SHELL=zsh,从旧容器克隆或重建时,Distrobox 首次初始化会因为找不到 zsh 而退出。

--nvidia 会把宿主机 NVIDIA 用户态驱动集成进容器;三个环境变量则让 OpenGL/Vulkan 默认选择 NVIDIA,避免落回旧 Mesa 的 llvmpipe 软件渲染。

2.3 首次进入容器(初始化)

BASH
distrobox enter ros-melodic-box

首次进入会自动安装约 200 多个基础包,耗时 3~5 分钟,不要中断

三、容器内配置

3.1 配置华为云 Ubuntu 镜像源

容器内基础镜像缺少 CA 证书,先使用 HTTP 源安装证书,再切换到 HTTPS:

BASH
# 先使用 HTTP 源
sudo tee /etc/apt/sources.list << 'EOF'
deb http://mirrors.huaweicloud.com/repository/ubuntu/ bionic main restricted universe multiverse
deb http://mirrors.huaweicloud.com/repository/ubuntu/ bionic-updates main restricted universe multiverse
deb http://mirrors.huaweicloud.com/repository/ubuntu/ bionic-backports main restricted universe multiverse
deb http://mirrors.huaweicloud.com/repository/ubuntu/ bionic-security main restricted universe multiverse
EOF

sudo apt update
sudo apt install -y ca-certificates

# 切换到 HTTPS 源
sudo tee /etc/apt/sources.list << 'EOF'
deb https://mirrors.huaweicloud.com/repository/ubuntu/ bionic main restricted universe multiverse
deb https://mirrors.huaweicloud.com/repository/ubuntu/ bionic-updates main restricted universe multiverse
deb https://mirrors.huaweicloud.com/repository/ubuntu/ bionic-backports main restricted universe multiverse
deb https://mirrors.huaweicloud.com/repository/ubuntu/ bionic-security main restricted universe multiverse
EOF

sudo apt update

3.2 安装基础工具

BASH
sudo apt install -y \
    curl gnupg2 lsb-release software-properties-common \
    git build-essential \
    python-rosdep python-rosinstall \
    python-rosinstall-generator python-wstool \
    mesa-utils

python-catkin-tools 通过 pip 安装:

BASH
sudo apt install -y python-pip
sudo pip install catkin_tools

四、安装 ROS Melodic

4.1 添加华为 ROS 镜像源

BASH
sudo tee /etc/apt/sources.list.d/ros-latest.list << 'EOF'
deb https://mirrors.huaweicloud.com/ros/ubuntu/ bionic main
EOF

curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | sudo apt-key add -
sudo apt update

4.2 安装 ROS Melodic 完整版

BASH
sudo DEBIAN_FRONTEND=noninteractive apt install -y ros-melodic-desktop-full

安装包约 500MB,解压后约 2.3GB,请耐心等待。

4.3 修复依赖冲突

安装完成后可能出现 python-rospkg-modules / python-rosdistro-modules 与旧包文件冲突,执行:

BASH
sudo apt -o Dpkg::Options::=--force-overwrite install -y \
    python-rospkg-modules python-rosdistro-modules python-catkin-pkg-modules

sudo apt --fix-broken install -y

4.4 验证安装

BASH
dpkg -l | grep ros-melodic-desktop-full
# ii  ros-melodic-desktop-full  1.4.1-0bionic.20230620.175308  amd64  ...

五、环境变量配置

将 ROS 环境变量添加到 ~/.bashrc

BASH
echo "source /opt/ros/melodic/setup.bash" >> ~/.bashrc
source ~/.bashrc

验证版本:

BASH
rosversion -d
# 输出:melodic

六、创建 catkin 工作空间(可选)

BASH
mkdir -p ~/catkin_ws/src
cd ~/catkin_ws/src
# 在这里 git clone 需要的 ROS 包
cd ~/catkin_ws
catkin_make

如果有工作空间,也加到 ~/.bashrc

BASH
echo "source ~/catkin_ws/devel/setup.bash" >> ~/.bashrc

七、测试 ROS 环境

在容器内执行以下命令测试:

BASH
source /opt/ros/melodic/setup.bash

# 启动 ROS Master
roscore &
sleep 3

# 查看话题列表
rostopic list
# 预期输出:
# /rosout
# /rosout_agg

# 发布测试消息
rostopic pub -1 /test std_msgs/String 'data: "hello ros melodic"'

# 接收测试消息
rostopic echo -n 1 /test
# 预期输出:
# data: "hello ros melodic"
# ---

# 启动 talker / listener
rosrun roscpp_tutorials talker &
rosrun roscpp_tutorials listener

如果 rostopic echo 能收到消息、talker/listener 正常输出,说明 ROS 环境配置成功。

八、日常使用

8.1 进入容器

BASH
distrobox enter ros-melodic-box

8.2 在宿主机直接执行容器内 ROS 命令

BASH
# 编译工作空间
distrobox enter ros-melodic-box -- bash -c "source /opt/ros/melodic/setup.bash && cd ~/catkin_ws && catkin_make"

# 直接运行 launch 文件
distrobox enter ros-melodic-box -- bash -c "source /opt/ros/melodic/setup.bash && roslaunch your_package your.launch"

8.3 验证 NVIDIA 硬件加速

直接检查默认 renderer,不需要每次手动添加 PRIME 环境变量:

BASH
nvidia-smi --query-gpu=name,driver_version --format=csv,noheader
glxinfo -B

本机实际输出:

TEXT
NVIDIA GeForce RTX 5070 Ti Laptop GPU, 610.43.02
direct rendering: Yes
OpenGL vendor string: NVIDIA Corporation
OpenGL renderer string: NVIDIA GeForce RTX 5070 Ti Laptop GPU/PCIe/SSE2
OpenGL core profile version string: 4.6.0 NVIDIA 610.43.02

除了 glxinfo,还要实际启动一次 RViz。测试时检查 RViz 进程的 /proc/$PID/maps,确认加载的是:

TEXT
libGLX_nvidia.so.0
libnvidia-glcore.so.610.43.02

并且没有加载 iris_dri.soswrast_dri.so。这比只看“窗口能够打开”更可靠,因为 llvmpipe 同样可能显示 direct rendering: Yes

这个容器原本使用 Mesa 20.0.8,远早于 Intel Arrow Lake-S 核显 8086:7d67。未启用 NVIDIA 集成时,RViz 会明确报错:

TEXT
Driver does not support the 0x7d67 PCI ID.
libGL error: failed to load driver: iris

不要为了核显支持去升级 Ubuntu 18.04 的 Mesa 或 glibc;这会增加破坏 ROS Melodic 和后文 VSCodium 兼容环境的风险。

8.4 停止/删除容器

BASH
# 停止
distrobox stop ros-melodic-box

# 删除容器(保留家目录数据)
distrobox rm ros-melodic-box

# 完全删除容器和数据
podman stop ros-melodic-box
podman rm ros-melodic-box
rm -rf ~/distrobox-homes/ros-melodic

九、数据备份

所有代码和配置都保存在宿主机的 ~/distrobox-homes/ros-melodic/ 下:

BASH
# 备份整个环境
tar czvf ros-melodic-backup.tar.gz ~/distrobox-homes/ros-melodic/

即使容器被删除,只要保留该目录,重建容器时指定同一个 --home 即可恢复。

十、常见问题

问题 解决
容器首次进入失败/退出 等待初始化完成(3~5 分钟),不要按 Ctrl+C
apt update 证书错误 先换 HTTP 源安装 ca-certificates,再切 HTTPS
python-rospkg-modules 文件冲突 使用 --force-overwrite 安装
串口无权限 宿主机执行 sudo usermod -aG dialout $USER,注销重新登录
GUI 程序无法显示 确保在桌面环境运行,Distrobox 会自动透传 DISPLAY
RViz 报不支持 0x7d67 或使用 llvmpipe 使用带 --nvidia 和 PRIME 环境变量的创建命令重建容器

十一、为什么不用 rosdep?

本方案固定使用 Ubuntu 18.04,所有依赖均可通过 apt 直接安装。rosdep 在国内网络环境下经常初始化失败,因此本教程选择只用 apt 管理依赖,简化环境搭建流程。


十二、VS Code / VSCodium 集成开发环境(踩坑记录)

12.1 为什么要把编辑器也放进容器

如果只在宿主机装 VS Code,C/C++ 扩展的 LSP(clangd / cpptools)和 Python 扩展会读取宿主机的头文件和解释器,导致:

  • C++ 跳转、补全看到的是宿主机的库;
  • Python 解释器路径对不上;
  • compile_commands.json 里的路径和宿主机不一致。

正确做法是让 VS Code 自身运行在容器里,这样所有 LSP、终端、调试器都在 Ubuntu 18.04 + ROS Melodic 环境中。

12.2 微软 VS Code + Dev Containers 的坑

Distrobox 本质是一个 Podman/Docker 容器,理论上可以用 Dev Containers 扩展 Attach。但微软 VS Code Server 从某版本开始要求容器内 glibc >= 2.28,而 Ubuntu 18.04 只有 2.27,会直接报错:

TEXT
Warning: Missing GLIBC >= 2.28! from /lib/x86_64-linux-gnu/libc-2.27.so
Error: Missing required dependencies.

所以 微软 VS Code 官方 Dev Containers 方案在老容器上走不通,需要换 VSCodium。

12.3 VSCodium + open-remote-distrobox 方案

  1. 安装 VSCodium

  2. 在 VSCodium 扩展市场里安装 open-remote-distrobox

  3. 如果已有容器,不要直接删除,否则系统级安装的软件(如 /opt/ros/melodic)会丢失。--home 只保存家目录里的代码和配置。

    正确做法是在原容器上继续用,或者用 podman commit 备份后再重建。如果确实要重建,创建命令如下:

BASH
# 重新创建,指向原来的家目录
distrobox create \
  --image ubuntu:18.04 \
  --name ros-melodic-box \
  --home ~/distrobox-homes/ros-melodic

注意--home 只保留 ~/distrobox-homes/ros-melodic/ 下的文件。/opt/ros/melodic/usr/local 等系统目录在删除容器时会一起消失。重建后需要重新安装 ROS。

  1. 在 VSCodium 里按 Ctrl+Shift+PRemote: Connect to Host...,输入:
TEXT
distrobox+ros-melodic-box
  1. 等待 VSCodium Server 下载并启动,然后打开 ~/catkin_ws 或你的工作目录。

12.4 关键:替换 VSCodium Server 的 node

第一次连接时,VSCodium 会把 Server 下载到容器内的 ~/.vscodium-server/bin/。Ubuntu 18.04 的 glibc 只有 2.27,而 VSCodium Server 自带的 node 需要 glibc 2.28,直接启动会报错:

TEXT
/home/jiang/.../.vscodium-server/bin/.../node:
/lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.28' not found

解决办法是用 unofficial-builds.nodejs.orglinux-x64-glibc-217 版本替换它。下面以 1.126.04524 为例,版本号需要按实际目录调整:

BASH
distrobox enter ros-melodic-box -- bash -lc '
set -euo pipefail

version=1.126.04524
node_version=22.21.1
server="$HOME/.vscodium-server/bin/vscodium-reh-linux-x64-$version"
node_home="$HOME/.cache/node-unofficial/node-v$node_version-linux-x64-glibc-217"

mkdir -p "$HOME/.cache/node-unofficial"
cd "$HOME/.cache/node-unofficial"

if [ ! -x "$node_home/bin/node" ]; then
  curl -fL \
    "https://unofficial-builds.nodejs.org/download/release/v$node_version/node-v$node_version-linux-x64-glibc-217.tar.xz" \
    -o "node-v$node_version-linux-x64-glibc-217.tar.xz"
  tar -xf "node-v$node_version-linux-x64-glibc-217.tar.xz"
fi

[ -f "$server/node.vscodium-original-glibc228" ] || \
  cp -a "$server/node" "$server/node.vscodium-original-glibc228"
cp -a "$node_home/bin/node" "$server/node"
chmod 755 "$server/node"

"$server/node" -p "process.version + \" modules=\" + process.versions.modules"
'

注意:node_version 要和 VSCodium Server 当前使用的 Node 主版本匹配。至少要确认 process.versions.modules 没有变,否则 native addon 会出现 ABI 不匹配。

12.5 重新编译 VSCodium Server 的 native addon

只替换 node 还不够。以 VSCodium Server 1.126.04524 为例,服务主进程能启动,但 extension host 里仍可能出现这些错误:

TEXT
@parcel/watcher/build/Release/watcher.node: version `GLIBC_2.30' not found
@vscode/sqlite3/build/Release/vscode-sqlite3.node: version `GLIBC_2.29' not found
node-pty/build/Release/pty.node: version `GLIBC_2.28' not found

这些 .node 是 C/C++ native addon,官方包里的预编译产物是在更新的系统上编译的。不要升级容器 glibc;在 Ubuntu 18.04 容器里拉同版本源码重新编译即可。

先准备编译依赖:

BASH
distrobox enter ros-melodic-box -- bash -lc '
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
sudo apt update
sudo apt install -y python3.8 build-essential gcc-13 g++-13 libstdc++6 curl xz-utils
'

然后重新编译并替换三个 native addon:

BASH
distrobox enter ros-melodic-box -- bash -lc '
set -euo pipefail

version=1.126.04524
node_version=22.21.1
server="$HOME/.vscodium-server/bin/vscodium-reh-linux-x64-$version"
node_home="$HOME/.cache/node-unofficial/node-v$node_version-linux-x64-glibc-217"
work="$HOME/.cache/vscodium-native-builds/$version"

export PATH="$node_home/bin:$PATH"
export PYTHON=/usr/bin/python3.8
export CC=gcc-13
export CXX=g++-13
export SERVER_VERSION="$version"

mkdir -p "$work"
cd "$work"

npm pack @parcel/watcher@2.5.6 @vscode/sqlite3@5.1.12-vscode node-pty@1.2.0-beta.13

rm -rf parcel-watcher vscode-sqlite3 node-pty
mkdir parcel-watcher vscode-sqlite3 node-pty
tar -xzf parcel-watcher-2.5.6.tgz -C parcel-watcher --strip-components=1
tar -xzf vscode-sqlite3-5.1.12-vscode.tgz -C vscode-sqlite3 --strip-components=1
tar -xzf node-pty-1.2.0-beta.13.tgz -C node-pty --strip-components=1

cd "$work/parcel-watcher"
npm install --ignore-scripts
npx node-gyp rebuild

cd "$work/vscode-sqlite3"
npm install --ignore-scripts
npx node-gyp rebuild

cd "$work/node-pty"
npm install --ignore-scripts
npx node-gyp rebuild

copy_node() {
  src="$1"
  dst="$2"
  [ -f "$dst.vscodium-original-glibc-high" ] || cp -a "$dst" "$dst.vscodium-original-glibc-high"
  cp -a "$src" "$dst"
  chmod 755 "$dst"
}

copy_node "$work/parcel-watcher/build/Release/watcher.node" \
  "$server/node_modules/@parcel/watcher/build/Release/watcher.node"
copy_node "$work/vscode-sqlite3/build/Release/vscode-sqlite3.node" \
  "$server/node_modules/@vscode/sqlite3/build/Release/vscode-sqlite3.node"
copy_node "$work/node-pty/build/Release/pty.node" \
  "$server/node_modules/node-pty/build/Release/pty.node"

"$server/node" - <<EOF
const base = process.env.HOME + "/.vscodium-server/bin/vscodium-reh-linux-x64-" + process.env.SERVER_VERSION + "/node_modules";
for (const pkg of ["@parcel/watcher", "@vscode/sqlite3", "node-pty"]) {
  require(base + "/" + pkg);
  console.log(pkg + ": ok");
}
EOF
'

这里还有一个容易误判的坑:@parcel/watcherrequire() 成功不代表 file watcher 正常。VSCodium 的 file watcher 还会启动独立子进程调用 @parcel/watcher.subscribe() / writeSnapshot()。这些 native 路径在当前 Ubuntu 18.04 容器里仍可能段错误:

TEXT
IPC "File Watcher" crashed with exit code null and signal SIGSEGV

我这里的处理方式是把 @parcel/watcher/wrapper.js 里的 writeSnapshot()getEventsSince()subscribe() 都改成 JS 实现:snapshot 用递归扫描,subscribe 用定时轮询 diff。这样会牺牲一点文件变更实时性,但可以避开会崩溃的 native watcher。修改前先备份:

BASH
distrobox enter ros-melodic-box -- bash -lc '
for version in 1.126.04524 1.121.03429; do
  f="$HOME/.vscodium-server/bin/vscodium-reh-linux-x64-$version/node_modules/@parcel/watcher/wrapper.js"
  [ -f "$f" ] || continue
  [ -f "$f.vscodium-original-native-snapshot" ] || cp -a "$f" "$f.vscodium-original-native-snapshot"
done
'

补丁思路很简单:

  • writeSnapshot() 用 JS 递归扫描目录,写入 JSON 快照;
  • getEventsSince() 再扫描一次目录,对比 JSON 快照,返回 create / update / delete 事件。
  • subscribe() 先扫描一次目录,然后用 setInterval 定时 diff,有变化时回调事件;
  • unsubscribe() 清理这个 JS 定时器,不再调用 native binding.unsubscribe()

修改后可以这样验证 snapshot 和 subscribe 都不再段错误:

BASH
distrobox enter ros-melodic-box -- bash -lc '
nodebin="$HOME/.vscodium-server/bin/vscodium-reh-linux-x64-1.126.04524/node"
mod="$HOME/.vscodium-server/bin/vscodium-reh-linux-x64-1.126.04524/node_modules/@parcel/watcher"
tmp="$(mktemp -d)"
snap="$(mktemp)"
rm -f "$snap"
echo a > "$tmp/a.txt"

MOD="$mod" WATCH_DIR="$tmp" SNAP="$snap" "$nodebin" -e "
const fs = require(\"fs\");
const path = require(\"path\");
const watcher = require(process.env.MOD);
(async () => {
  const dir = process.env.WATCH_DIR;
  const snap = process.env.SNAP;
  await watcher.writeSnapshot(dir, snap, { ignore: [] });
  fs.writeFileSync(path.join(dir, \"a.txt\"), \"aa\");
  fs.writeFileSync(path.join(dir, \"b.txt\"), \"b\");
  const events = await watcher.getEventsSince(dir, snap, { ignore: [] });
  console.log(events.map(e => e.type + \":\" + path.basename(e.path)).sort().join(\",\"));
})().catch(e => { console.error(e.stack); process.exit(1); });
"

rm -rf "$tmp" "$snap"
'
# 预期:create:b.txt,update:a.txt

再验证 subscribe()

BASH
distrobox enter ros-melodic-box -- bash -lc '
nodebin="$HOME/.vscodium-server/bin/vscodium-reh-linux-x64-1.126.04524/node"
tmp="$(mktemp -d)"

WATCH_DIR="$tmp" VSCODIUM_PARCEL_WATCHER_POLL_INTERVAL=500 "$nodebin" -e "
const fs = require(\"fs\");
const path = require(\"path\");
const watcher = require(process.env.HOME + \"/.vscodium-server/bin/vscodium-reh-linux-x64-1.126.04524/node_modules/@parcel/watcher\");
const dir = process.env.WATCH_DIR;
(async () => {
  const sub = await watcher.subscribe(dir, (err, events) => {
    if (err) {
      console.error(err.stack || err);
      process.exit(1);
    }
    console.log(events.map(e => e.type + \":\" + path.basename(e.path)).sort().join(\",\"));
    sub.unsubscribe();
    process.exit(0);
  }, { ignore: [] });
  setTimeout(() => fs.writeFileSync(path.join(dir, \"poll.txt\"), \"x\"), 100);
  setTimeout(() => {
    sub.unsubscribe();
    process.exit(2);
  }, 3000);
})().catch(e => { console.error(e.stack); process.exit(1); });
"

rm -rf "$tmp"
'
# 预期:create:poll.txt

最后重连 distrobox+ros-melodic-box。如果已经有失败的 server 进程,可以先从宿主机停止它:

BASH
distrobox enter ros-melodic-box -- bash -lc '
control="/run/user/1000/distrobox-vscodium-server-linux-x64-1.126.04524-ros-melodic-box/control-0.3.2.sh"
[ -x "$control" ] && "$control" stop || true
'

如果 VSCodium 已经打开了远程窗口,重启 server 后可能一直弹出“无法重新连接,请重新加载窗口”。日志里通常是:

TEXT
Unknown reconnection token (never seen).

这是因为 reconnection token 只存在旧 server 进程内存里,server 被停止后无法恢复。实测只点“重新加载窗口”不一定够,需要完整退出并重启 VSCodium,让 open-remote-distrobox 重新走初始化流程。

12.6 常见错误速查

错误 原因 解决
failed to launch server in guest distro,日志里有 /run/user/1000/.../control.sh not found open-remote-distrobox 的控制脚本路径在容器内不可见 检查 Distrobox 是否已默认挂载 /run/user/1000;若仍报错,尝试用 podman inspect 查看挂载,或给 open-remote-distrobox 提 issue
Missing GLIBC >= 2.28node: version GLIBC_2.28 not found VSCodium Server 自带的 node 需要 glibc 2.28 按 12.4 替换为 glibc-217 版本 node
watcher.nodevscode-sqlite3.nodepty.nodeGLIBC_2.28/2.29/2.30 not found Server 自带 native addon 的预编译产物不兼容 Ubuntu 18.04 按 12.5 在容器里重新编译同版本 native addon
IPC "File Watcher" crashed ... SIGSEGV @parcel/watcher 的 native subscribe() / snapshot 路径在当前 18.04 环境里段错误 wrapper.jswriteSnapshot()getEventsSince()subscribe() 都改成 JS 降级实现
一直弹“无法重新连接”,日志为 Unknown reconnection token 修改过程中重启了 server,旧窗口的 reconnect token 已失效 完整退出并重启 VSCodium,不要继续等待自动重连
删除容器后 ROS 没了 --home 不保存 /opt/ros 等系统目录 删除前用 podman commit 备份镜像,或重建后重新 apt install ros-melodic-desktop-full
VSCodium Server 下载失败 容器内访问 GitHub 受阻 容器内配置代理,或手动下载对应版本放到 ~/.vscodium-server/bin/

12.7 推荐在容器内安装的扩展

连接成功后,在容器内安装:

  • llvm-vs-code-extensions.vscode-clangd(C++ 补全)
  • ms-vscode.cpptools(调试)
  • ms-python.python(Python)
  • ms-ros-vscode.ros(ROS 语法高亮,如果可用)

这些扩展都会运行在容器内,看到的是 ROS Melodic 的真实环境,C++ LSP 终于不再索引本机库了。

12.8 实际项目编译依赖示例

在容器里编译真实 ROS 包时,可能会缺少一些非 ros-melodic-desktop-full 自带的依赖。根据实际项目经验,可能需要安装:

BASH
sudo apt-get update

# 点云/SLAM 相关
sudo apt-get install -y ros-melodic-octomap-ros
sudo apt-get install -y libsuitesparse-dev
sudo apt-get install -y ros-melodic-apriltag

# 导航/规划相关
sudo apt-get install -y ros-melodic-costmap-2d
sudo apt-get install -y ros-melodic-teb-local-planner

# RealSense 相关
sudo apt-get install -y ros-melodic-librealsense2
sudo apt-get install -y ros-melodic-realsense2-camera
sudo apt-get install -y ros-melodic-realsense2-description

# 系统库
sudo apt-get install -y libpcap-dev
sudo apt-get install -y libpulse-dev
sudo apt-get install -y libvlc-dev

提示:不同项目依赖不同。如果编译报错 Could not find a package configuration file provided by ...,根据提示用 apt search ros-melodic-xxxapt search libxxx-dev 安装对应包即可。

12.9 CMake 4 兼容性处理

容器内源码编译安装的 CMake 4.0+ 对老项目的 cmake_minimum_required 更严格,可能会报错:

TEXT
Compatibility with CMake < 3.5 has been removed from CMake 4.0.

解决办法是设置兼容变量:

BASH
export CMAKE_POLICY_VERSION_MINIMUM=3.5

建议把它写进 ~/.bashrc,这样每次构建自动生效:

BASH
echo 'export CMAKE_POLICY_VERSION_MINIMUM=3.5' >> ~/.bashrc
source ~/.bashrc