Mian的笔记
  • 首页
  • 文档 ▾
    • 无人机实验
    • 无人机工程
    • 杂记
  • 关于
输入关键词开始搜索

9.1_Docker标准化运行环境

Mian 发布于 2026-05-13

  • 📒 无人机实验
  • 🏷️ ROS1
  • 🏷️ 仿真
  • 🏷️ FlightMare
  • 🏷️ Unity
  • 🏷️ docker
  • 🏷️ vitfly

二编前言

以下内容仅供参考,并不推荐复现

之前由于ubuntu 20.04上内核过老,对于一些应用的GUI不支持,一直想要升级。而正好服务器上在使用docker来运行实验(采集数据),于是想到了在本地也使用docker,同时也可以给电脑升级。但是在绕了一圈后发现了许多问题。

首先是在服务器上使用docker,大部分情况其实没有必要,因为服务器上由于计算资源不固定,对于测试和数据采集来说会影响呈现结果,因而仅推荐进行模型训练,而模型训练大部分情况下则只需要使用python环境;同时如果要在服务器上测试与采集数据,虚拟屏幕的配置会比较复杂,而测试结果(例如视频)的回传也会比较复杂。于是,推荐在本地PC上进行数据的采集与测试。而在本地使用docker,一是镜像会占用大量空间;二是配置复杂,多出了许多操作。综上所述,虽然采用docker可以标准化训练与测试环境,但是带来的额外操作也非常多,个人在此处选择放弃docker的使用。

前言

在运行vitfly无人机仿真数据采集时,发现在headless服务器运行虚拟显示器,采集视觉数据总会遇到问题,于是改为在本地PC上采集数据。而为了标准化,想到本地环境也可以使用docker。

镜像构建

首先给出如下的Dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
FROM nvidia/cuda:11.8.0-devel-ubuntu20.04

ENV DEBIAN_FRONTEND=noninteractive
ENV TZ=Etc/UTC

# ---- ROS 仓库 + 系统基础依赖 + ROS Noetic ----
RUN apt update && apt install -y curl gnupg2 lsb-release && \
sh -c 'echo "deb http://packages.ros.org/ros/ubuntu focal main" > /etc/apt/sources.list.d/ros-latest.list' && \
curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | apt-key add - && \
apt update && \
apt install -y --no-install-recommends ros-noetic-desktop-full

# ---- 系统依赖 ----
RUN apt-get update && apt-get install -y --no-install-recommends \
git \
python3-pip \
build-essential \
cmake \
libzmqpp-dev \
libopencv-dev \
unzip \
python3-catkin-tools \
mesa-utils \
libxcb-icccm4 \
libxcb-image0 \
libxcb-keysyms1 \
libxcb-randr0 \
libxcb-render-util0 \
libxcb-shape0 \
libxcb-xinerama0 \
libxcb-xkb1 \
libxkbcommon-x11-0 \
&& rm -rf /var/lib/apt/lists/*

# ---- python 依赖 ----
RUN pip3 config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
RUN pip3 install --no-cache-dir \
torch==2.4.1 \
torchvision==0.19.1 \
numpy==1.24.4 \
pandas==2.0.3 \
matplotlib==3.7.5 \
opencv-python==4.10.0.84 \
pyyaml==5.3.1 \
uniplot==0.16.2 \
ConfigArgParse==1.7 \
scipy \
tensorboard==2.14.0

# ---- ros 初始化 + bashrc ----
RUN echo "source /opt/ros/noetic/setup.bash" >> /root/.bashrc

ENV FLIGHTMARE_PATH=/root/vitfly_ws/src/vitfly/flightmare
ENV NVIDIA_DRIVER_CAPABILITIES=compute,graphics,display

SHELL ["/bin/bash", "-c"]
CMD ["bash"]

其中的基础镜像部分,ros官方其实提供了自己的docker镜像,可以用以下方式拉取

1
sudo docker pull osrf/ros:noetic-desktop-full

但是由于本实验需要使用nvidia显卡即会用到cuda,可以预见的从配置好cuda的基础镜像去下载ros,会比从配置好ros的基础镜像去下载cuda更方便。在dockerfile所在文件夹运行docker build -t vitlfy .构建镜像

本地运行

使用以下脚本来运行容器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Allow Docker containers to connect to the X server
xhost +local:docker > /dev/null 2>&1

docker run -it --rm \
--gpus all \
--device=/dev/dri:/dev/dri \
--ipc=host \
-v /tmp/.X11-unix:/tmp/.X11-unix:rw \
-e DISPLAY=$DISPLAY \
-e QT_X11_NO_MITSHM=1 \
-e XAUTHORITY=/root/.Xauthority \
-v $HOME/.Xauthority:/root/.Xauthority:ro \
-e XDG_RUNTIME_DIR=/tmp \
-v path/to/vitfly_ws:/root/vitfly_ws \
--network host \
--name vitfly \
vitfly

这里有许多参数的作用是为了让容器中运行的程序能够在宿主机上显示出来

服务器运行

在服务器上运行时,由于unity刚需显示器的特性,需要在服务器上运行虚拟屏幕,于是在dockerfile中加入以下内容

1
2
3
4
5
6
7
8
COPY docker-entrypoint.sh /docker-entrypoint.sh
RUN chmod +x /docker-entrypoint.sh

ENV DISPLAY=:99

SHELL ["/bin/bash", "-c"]
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["bash"]

其中docker-entrypoint.sh内容如下

1
2
3
4
5
6
7
8
#!/bin/bash
# Start virtual X server for headless rendering (Unity needs a display)
Xvfb :99 -screen 0 1024x768x24 -ac +extension GLX +render &

# Source ROS environment
source /opt/ros/noetic/setup.bash

exec "$@"

然后运行脚本如下

1
2
3
4
5
6
docker run -d \
--gpus all \
--network host \
-v path/to/vitfly_ws:/root/vitfly_ws \
--bane vitfly
vitfly tail -f /dev/null

Dockerfile

首先需要简单说明dockerfile的SHELL,ENTRYPOINT,CMD命令的作用与区别
SHELL:指定命令的执行环境

  • 作用: 改变 Dockerfile 中后续指令(如 RUN、CMD、ENTRYPOINT)在 shell 格式下所使用的默认 Shell 解析器。
  • 默认值: Linux 系统默认是 [“/bin/sh”, “-c”];Windows 系统默认是 [“cmd”, “/S”, “/C”]。
  • 应用场景: 想在 Linux 中改用 bash 或 zsh,或者在 Windows 中改用 powershell 时使用。

ENTRYPOINT:指定容器的“主程序”

  • 作用: 设置容器启动时必然会执行的命令。它让容器看起来像一个独立的“可执行文件”。
  • 特点: 除非在 docker run 时显式加上 –entrypoint 参数,否则它不会被覆盖。

CMD:指定默认参数或默认命令

  • 作用: 为容器提供默认的执行命令或参数。
  • 特点: 它是极易被覆盖的。如果在 docker run 后面跟了任何附加命令,CMD 就会被完全忽略。

具体而言,SHELL的作用还算好理解,后两者的使用需要举例来说明
场景 A:单独使用 CMD

1
2
FROM ubuntu
CMD ["echo", "Hello World"]
  • docker run my-image ➡️ 输出 Hello World
  • docker run my-image echo "Hi" ➡️ 输出 Hi(CMD 被覆盖了)

场景 B:单独使用 ENTRYPOINT

1
2
FROM ubuntu
ENTRYPOINT ["echo", "Hello"]
  • docker run my-image ➡️ 输出 Hello
  • docker run my-image World ➡️ 输出 Hello World(传给容器的参数直接追加到了主程序后面!)

场景 C:ENTRYPOINT 与 CMD 组合使用
这是最工业级的用法。ENTRYPOINT 定死主程序,CMD 提供默认参数:

1
2
3
FROM ubuntu
ENTRYPOINT ["ping", "-c", "3"]
CMD ["localhost"]
  • docker run my-image ➡️ 实际执行 ping -c 3 localhost(默认拼本地)
  • docker run my-image 8.8.8.8 ➡️ 实际执行 ping -c 3 8.8.8.8(CMD 的默认参数被覆盖,换成了拼外网)

docker-entrypoint.sh

在了解了上述内容后,可以知道ENTRYPOINT ["/docker-entrypoint.sh"]的作用就是运行该脚本

1
Xvfb :99 -screen 0 1024x768x24 -ac +extension GLX +render &

其中Xvfb为linux的虚拟屏幕指令,设置端口为99并在后台运行。对应的,需要在dockerfile中加入以下两部分:

  1. 首先是设置环境变量ENV DISPLAY=:99告诉系统里的程序,后续画面都渲染到刚才的虚拟屏幕中
  2. 提供脚本。该脚本是在构建镜像时传入到系统中的,当镜像构建完成之后便写死在了系统内。
    1
    2
    COPY docker-entrypoint.sh /docker-entrypoint.sh
    RUN chmod +x /docker-entrypoint.sh

运行脚本

上一步中使用脚本创建了虚拟屏幕,但是一旦该脚本结束,那么虚拟屏幕也就结束了,所以需要一些操作来维持虚拟屏幕。一是在.sh末尾有这样的内容:exec "$@",二是在运行脚本的末尾,加入了这样的内容tail -f /dev/null,接下来分别进行解释。

exec "$@"
简单来说该命令就是执行传给容器的后续参数(之前提到的会覆盖CMD的部分)。

  • **"$@"**:代表传给容器的所有后续参数。该场景下,"$@" 对应的就是 tail -f /dev/null
  • exec:Linux 的一个内置命令。它的特点是启动一个新进程,并用这个新进程完全替换掉当前的 Shell 进程,同时保持原有的进程 ID(PID)不变。这样在应用结束时,系统可以找到该脚本并关闭。

tail -f /dev/null
相当于在脚本内执行该指令。其中/dev/null是linux默认的空文件,无法读取到任何内容,而tail -f则是代表跟踪某文件的最新内容。两者加在一起则会让脚本无限阻塞,从而让脚本不会退出。

后续改进

尝试是否能在服务器上的容器中用虚拟显示器来采集数据,现在采集了数据还要上传到服务器还是太复杂了,希望本地仅用来运行测试。

zotero文件同步修复

下一篇

Docker 入门知识

上一篇
Mian

Mian

每天成长一点

26
3
33
目录
  1. 1. 二编前言
  2. 2. 前言
    1. 2.1. 镜像构建
    2. 2.2. 本地运行
    3. 2.3. 服务器运行
      1. 2.3.1. Dockerfile
      2. 2.3.2. docker-entrypoint.sh
      3. 2.3.3. 运行脚本
  3. 3. 后续改进
CATEGORIES
  • 无人机实验 (17)
  • 无人机工程 (8)
  • 杂记 (1)
TAGS
AprilTag CPP FlightMare Gazebo IntelRealsenseD435 MAVROS NUC13 Python ROS1 Ubuntu20-04 Unity astar catkin cmake docker drone octomap px4 rosbag vins vitfly zotero 仿真 修复 动力学 参数服务器 坚果云 实机 建图 模块化 视觉定位 路径规划 飞控

© 2026 Mian

Powered by Hexo Theme - flex-block

🌞 浅色 🌛 深色 🤖️ 自动