Bootstrap

Docker搭建ORB-SLAM3相关开发环境

Docker搭建ORB-SLAM3相关开发环境

目前已经构建了orb-slam3的开发环境,下载orb-slam3-dev的tar压缩包,按照下文介绍进行安装。

链接:https://pan.baidu.com/s/1LMLH5pUJZ6oszEezX2ArsA?pwd=fzn2

提取码:fzn2

百度网盘下载后解压,对于熟悉docker用户,快速上手按照4.2加载和保存镜像。

1. Docker简介

1.1. Docker 优势

Docker是一个开源的应用容器化平台,它让开发者可以打包他们的应用及其依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。Docker 提供了一套标准的运行、构建、分发应用的解决方案,可以让应用的部署工作更加高效、快捷和一致性。

**与传统虚拟机相比的优势:**Docker 和传统虚拟机技术虽然都提供了应用程序的隔离环境,但它们在架构、资源利用率、启动速度、便携性等方面存在显著差异:

  • 更轻量级:

    • Docker:容器共享主机的内核,不需要为每个应用配备完整的操作系统,因此体积更小,启动更快。
    • 虚拟机:每个VM包含一个完整的Guest OS,消耗更多资源,启动慢。
  • 更高的资源利用率:

    • Docker:由于轻量级特性,可以在同一硬件上运行更多的容器,极大地提高了资源利用效率。
    • 虚拟机:每个VM都需要分配独立的资源,即使未充分利用也会占用预定的资源。
  • 更快的启动速度:

    • Docker:容器几乎可以瞬间启动,适合频繁创建和销毁的场景。
    • 虚拟机:启动涉及到整个操作系统的加载,耗时较长。
  • 更好的可移植性和一致性:

    • Docker:通过Dockerfile定义应用环境,确保了“一次构建,到处运行”,降低了环境差异带来的问题。
    • 虚拟机:虽然也支持迁移,但因其包含整个操作系统,迁移复杂度相对较高。
  • 更简单的管理与部署:

    • Docker:通过Docker CLI或Docker Compose等工具,可以轻松管理容器和应用栈,自动化程度高。
    • 虚拟机:管理通常需要更复杂的虚拟化管理平台,操作相对繁琐。
  • 更高效的开发与测试环境:

    • Docker:便于开发者快速搭建与销毁开发、测试环境,加速迭代周期。
    • 虚拟机:创建和配置新的开发环境通常耗时较长。

Docker 以其轻量化、高效、灵活的特性,在现代软件开发、持续集成、微服务架构等领域得到了广泛的应用。与传统虚拟机相比,它在资源效率、部署速度、环境一致性等方面展现出了明显优势,成为了现代云原生技术栈中的重要组成部分。使用docker搭建ORB-SLAM3相关的开发环境,可以保证开发、测试、应用环境一样,减少在环境不同导致的bug。

1.2. Docker概念

仓库(Repository):用于存储Docker镜像的地方,类似于源代码控制系统中的代码库。Docker仓库可以是公共的,如Docker Hub,也可以是私人的。

镜像(Image):它是Docker容器的运行时模板,由多个层(layers)组成。每个镜像都包含了一系列修改后的层,当应用更新或升级时,会生成一个新的层。

容器(Container):这是Docker的运行实体,它包含了应用程序所需的所有环境和配置。容器可以在运行状态下被创建、启动、停止、移动和删除。

Docker Client:用户通过这个客户端与Docker守护进程进行交互。

​ Docker Daemon:守护进程负责管理和调度Docker容器,设置成开机自启的服务

​ Docker Images:本机下载的镜像,由多个docker命令操作生成镜像层(只读)

​ Docker Repository:存放镜像的仓库,可以是公共的,如Docker Hub。

2. Docker 安装

本文只介绍ubuntu安装docker和开启docker服务,其他平台类似,安装可能更简便。

官⽹安装⽅法:https://docs.docker.com/engine/install/ubuntu/ 。

2.1. 更新软件包源
sudo apt-get update
sudo apt-get upgrade
2.2. 安装Docker的依赖项

Docker依赖于一些系统库和工具,特别是对于较旧的Linux发行版。安装这些依赖项:

sudo apt-get install apt-transport-https ca-certificates curl software-properties-common
2.3. 添加Docker的官方GPG密钥:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
2.4. 设置Docker稳定版存储库:
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
2.5. 安装Docker引擎:
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
2.6. 验证安装
sudo docker run hello-world

如果一切正常,你将看到hello from docker。img

2.7. 启动Docker服务:
sudo systemctl start docker   #  设置开启
sudo systemctl enable docker  # 设置开机启动
2.8. 网络问题

如果由于网络问题,这里推荐使用国内编写的脚本,会去国内的服务器下载,按照步骤下载,速度更快。

wget http://fishros.com/install -O fishros && . fishros
2.9. 配置国内镜像源

创建或修改 /etc/docker/daemon.json 文件,修改为如下形式:

{
  "registry-mirrors": [
    "https://registry.hub.docker.com",
    "http://hub-mirror.c.163.com",
    "https://mirror.baidubce.com",
    "https://docker.mirrors.sjtug.sjtu.edu.cn",
    "https://docker.nju.edu.cn"
  ]
}
拉取镜像源会从国内服务器,速度飞快,
systemctl restart docker

查看是否成功

docker info
hucheng@hucheng-T5-SKYLAKE:~$ docker info
Client: Docker Engine - Community
 Version:    24.0.2
 Context:    default
 Debug Mode: false
 Plugins:
  buildx: Docker Buildx (Docker Inc.)
    Version:  v0.10.5
    Path:     /usr/libexec/docker/cli-plugins/docker-buildx
  compose: Docker Compose (Docker Inc.)
    Version:  v2.18.1
    Path:     /usr/libexec/docker/cli-plugins/docker-compose
Server:
 Containers: 2
  Running: 1
  Paused: 0
  Stopped: 1
 Images: 4
 Server Version: 24.0.2
 Storage Driver: overlay2
  Backing Filesystem: extfs
  Supports d_type: true
  Using metacopy: false
  Native Overlay Diff: true
  userxattr: false
 Logging Driver: json-file
 Cgroup Driver: cgroupfs
 Cgroup Version: 1
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
 Swarm: inactive
 Runtimes: io.containerd.runc.v2 runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: 3dce8eb055cbb6872793272b4f20ed16117344f8
 runc version: v1.1.7-0-g860f061
 init version: de40ad0
 Security Options:
  apparmor
  seccomp
   Profile: builtin
 Kernel Version: 5.4.0-150-generic
 Operating System: Ubuntu 18.04.6 LTS
 OSType: linux
 Architecture: x86_64
 CPUs: 8
 Total Memory: 15.46GiB
 Name: hucheng-T5-SKYLAKE
 ID: 01ecf49b-70cb-43e2-9357-3fc22e7001aa
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Experimental: false
 Insecure Registries:
  127.0.0.0/8
 Registry Mirrors:
  https://dockerproxy.com/
  https://hub-mirror.c.163.com/
  https://mirror.baidubce.com/
  https://ccr.ccs.tencentyun.com/
 Live Restore Enabled: false

WARNING: No swap limit support

服务端也开启了,就可以与docker 守护进程通信。docker 也是CS架构,在命令行终端输入的命令需要被守护进程监听,守护进程挂了,docker运行就会报错。

2.10. 允许非root用户使用Docker

默认情况下,只有root用户可以运行Docker命令。如果你想允许其他用户使用Docker,可以将他们加入到docker组:

sudo usermod -aG docker your_username

3. Dockerfile

3.1. 简介

Dockerfile是一个用于自动构建Docker镜像的文本文件,它以一系列指令的形式定义了如何从基础镜像开始,逐步添加文件、安装软件包、设置环境变量、运行脚本等,直至最终形成一个新的自定义镜像的过程。Dockerfile的设计遵循从上至下的执行顺序,每条指令在构建过程中都会在前一层的基础上增加新的一层,从而形成了镜像的层次结构。

3.2. Dockerfile的基本结构和常用指令
  • FROM:Dockerfile的第一条指令必须是FROM,用来指定基础镜像。例如,FROM ubuntu:18.04 表示基于Ubuntu 18.04版本的镜像开始构建。
  • RUN:用于执行命令,可以是 shell 命令或执行可执行文件。每次RUN指令都会创建一个新的镜像层。例如,RUN apt-get update && apt-get install -y python3 安装Python3。
  • COPY:将本地文件或目录复制到镜像内部。例如,COPY . /app 将当前目录下的所有文件复制到镜像的/app目录。
  • ADD:类似COPY,但还支持自动解压URL指向的归档文件,并且可以将远程文件下载到镜像中。
  • WORKDIR:设置后续命令的默认工作目录,例如,WORKDIR /app 将工作目录设定为/app。
  • CMD:指定容器启动时默认执行的命令,可以被docker run命令行参数覆盖。例如,CMD [“python3”, “app.py”],注意只有最后一个CMD命令会生效,会被docker run 的命令参数覆盖(则不执行)
  • ENTRYPOINT:类似于CMD,用于配置容器启动时执行的命令,但它不会被docker run命令行参数覆盖,常与CMD一起使用来设置默认参数。
  • ENV:设置环境变量,例如,ENV MY_VAR=value。
  • EXPOSE:声明容器运行时监听的端口,但并不映射端口,例如,EXPOSE 8080。
  • VOLUME:创建数据卷挂载点,例如,VOLUME /data。
  • USER:指定运行容器时的用户,例如,USER nobody。

下面是一个dockerfile文件,拉取ros镜像,拷贝orb-slam3到镜像中,安装必要的开发工具。

# 使用ros官方镜像作为基础镜像
FROM  osrf/ros:melodic-desktop-full


# 安装必要的基础工具
RUN apt-get update && \
    DEBIAN_FRONTEND=noninteractive apt-get install -y \
        git \
        cmake \
        gcc \
        gedit\
        vim \
        wget \
        curl \
        unzip \
        libeigen3-dev \
        libopencv-dev \
        libboost-all-dev \
        libpcl-dev \
        build-essential

# 设置语言环境
ENV LANG en_US.UTF-8  
ENV LANGUAGE en_US:en  
ENV LC_ALL en_US.UTF-8  

# 添加用户并设置权限
RUN useradd -ms /bin/bash devuser && \
    echo "devuser:123" | chpasswd && \
    usermod -aG sudo devuser

# 切换到新用户以进行后续操作
USER devuser
WORKDIR /home/devuser

# 拷贝ORB-SLAM3
COPY slam_ws/ORB_SLAM3  /home/devuser/


# 编译 ORB-SLAM3
 RUN   cd ORB-SLAM3 && \
    chmod +x install.sh && \
    ./build.sh

# 安装 ORB-SLAM3 ros
RUN echo "export ROS_PACKAGE_PATH=${ROS_PACKAGE_PATH}:/home/devuser/ORB-SLAM3_WT/Examples/ROS" >> ~/.bashrc && \
    source ~/.bashrc && \
    chmod +x build_ros.sh && \
    ./build_ros.sh

# 安装ros usb_cam 驱动包
RUN apt install ros-melodic-usb-cam

# 拷贝kalibr (注意路径)
COPY slam_ws/calib_ws/src  calib_ws/

# 拷贝sdk

COPY slam_ws/sdk/IMSEE-SDK/   /home/devuser/sdk/IMSEE-SDK/
COPY slam_ws/sdk/librealsense-2.50.0   /home/devuser/sdk/
COPY slam_ws/sdk/realsense_ros/src   /home/devuser/sdk/

# 设置ENTRYPOINT,方便进入容器后直接启动bash
ENTRYPOINT ["/bin/bash"]

构建镜像时,推荐找官方镜像或者已经构建完整的镜像。对于官方镜像体积非常小,只有最基础的linux内核,适合非常轻量级的示例。完整的镜像提供了更多工具,适合做算法开发与测试。

3.3. Dockerfile优势
  • 可重复性:确保每次构建的镜像都是相同的,有利于持续集成和持续部署(CI/CD)流程。
  • 可维护性:Dockerfile作为代码的一部分,可以版本控制,便于追踪更改和协作。
  • 效率:通过分层构建,仅当某层内容变化时才会重新构建那一层,节省时间和资源。
  • 标准化:统一应用的部署和运行环境,降低环境差异带来的问题。

Dockerfile的编写遵循简洁和明确的原则,使得构建过程清晰可见,便于管理和维护,是Docker生态中构建镜像的重要工具。

4. 镜像

4.1. 构建镜像

根据上面的流程,编写dockerfile构建自己的镜像,运行命令:

docker build -t <image-name>[:<tag>] .

上面的命令会寻找当前目录下的Dockerfile文件,tag省略时,默认是latest版本。如果是其他名字,运行命令:

docker build -f /path/to/your/custom-Dockerfile -t my-image .
  • -f 或 --file 指定了Dockerfile的路径。
  • -t 用于指定构建后镜像的仓库名和标签。
  • . 表示上下文目录,Docker会从这个目录中获取Dockerfile以及COPY或ADD命令中引用的文件。即使你指定了-f来改变Dockerfile的位置,构建上下文仍然很重要,因为它定义了Docker能够访问哪些文件。
4.2. 加载和保存镜像

构建镜像过程比较复杂,需要等待较长的时间,因此推荐下载别人构建的镜像,只需要拷贝tar包,也可以将个人构建的镜像打包给人使用。

运行docker images 显示这是本人电脑下载的docker镜像:

hucheng@hucheng-T5-SKYLAKE:~$ docker images

REPOSITORY          TAG       IMAGE ID       CREATED       SIZE
orb-slam3-compile   1         f5ead81c107e   3 days ago    7.13GB
orb-slam3-dev       latest    3640663d2b5d   3 days ago    4.35GB
ubuntu              18.04     5a214d77f5d7   2 years ago   63.1MB
hello-world         latest    48b5124b2768   7 years ago   1.84kB
4.3. 使用docker save导出完整镜像(包括元数据和历史):
docker save -o my_image.tar my_image:tag

-o指定输出文件名,my_image是镜像名,:tag是镜像的标签,如果不指定,默认是latest。

4.4. 使用docker export导出运行时镜像状态:
docker export my_container > my_container.tar

注意,docker export需要容器ID或名称,而不是镜像名。

4.5. 加载Docker镜像

导出的tar文件可以通过docker load命令加载到Docker中,使其成为可用的镜像。

docker load -i my_image.tar

因此下载百度网盘的orb-slam3-dev包,运行下面命令加载镜像:

docker load -i orb-slam3-dev

或者,如果使用的是docker import命令来直接从tar文件创建一个新的镜像(这种方式不保留原有镜像的历史记录):

cat my_container.tar | docker import - my_new_image:tag

docker save和docker export用于导出镜像或容器为tar文件,适合于备份或传输;而docker load和docker import则用于将这些tar文件重新导入Docker,使之成为可运行的镜像。docker使用分层的概念,最上面是可写层,其他层都是可读层,有唯一的id,可读层可以服用,占用磁盘更小。

5. 容器

5.1. 简介

Docker容器是Docker技术的核心组成部分,它们是轻量级、可移植的运行时环境,用于执行应用程序及其所有依赖项。容器与宿主机共享操作系统内核,但拥有自己独立的文件系统、网络配置、进程空间等,从而实现了与主机和其他容器的隔离。下面是对Docker容器的基本使用方法。

5.2. 创建并启动容器
  • 使用 docker run:这是一步到位创建并启动容器的命令。例如,基于 ubuntu 镜像创建一个新容器,并运行交互式 Bash shell:
docker run -it  --name dev -v /home/path: ~/dev ubuntu /bin/bash

-i 表示使容器的标准输入保持打开,-t 分配一个伪TTY,–name 命令,-v 挂载 ,ubuntu 是镜像名

5.3. 启动已存在的容器
  • 使用 docker start:启动一个已创建但未运行的容器。需要提供容器的ID或名称:
docker start <容器ID或名称>
5.4. 停止容器
  • 使用 docker stop:停止运行中的容器。可指定容器ID或名称,并可设置超时时间:
docker stop [容器ID或名称] [-t|--time[=10]]
5.5. 重启容器
  • 使用 docker restart:重启一个容器。同样需要容器的ID或名称:
docker restart [容器ID或名称]
5.6. 删除容器
  • 使用 docker rm:删除已停止的容器。对于运行中的容器,需加 -f 强制删除:
docker rm [容器ID或名称]
若要删除所有容器(包括运行中的),可以结合 docker ps -aq 列出所有容器ID,然后传递给 rm 命令: 
docker rm $(docker ps -aq)
5.7. 查看容器
  • 使用 docker ps:列出正在运行的容器。使用 -a 参数可以查看所有容器(包括停止的):
docker ps [-a]
5.8. 进入容器
  • 使用 docker exec:在运行中的容器中执行命令,常用于进入容器的shell:
docker exec -it [容器ID或名称] /bin/bash
  • 使用 docker attach:直接附加到容器的标准输入输出流,但不如 exec 方便管理:
docker attach [容器ID或名称]
5.9. 导入和导出容器
  • 导出容器:使用 docker export 命令将容器保存为tar文件:
docker export [容器ID或名称] > container.tar
  • 导入容器:使用 docker import 命令将tar文件导入为新的镜像,然后可以基于该镜像启动容器:
cat container.tar | docker import - new_image_name:tag
5.10. 运行容器完整命令

docker 容器启动后的名称唯一,下面是一个完整的运行和进入docker容器的命令:

docker run \
    --detach, -d \
    --name my_container_name \
    --restart always \
    --volume /host/dir:/container/dir:ro \
    --publish 8080:80 \
    --env VAR1=value1 \
    --env-file ./env.list \
    --memory="512m" \
    --cpus="0.5" \
    --network my_network \
    --mac-address="02:42:ac:11:65:43" \
    --dns 8.8.8.8 \
    --dns-search example.com \
    --user 1000:1000 \
    --workdir /app \
    --read-only \
    --security-opt label=disable \
    --cap-add=SYS_ADMIN \
    --device=/dev/sdc \
    --privileged \
    --runtime=runc \
    my_image:tag \
    command arg1 arg2

这个命令的各部分含义如下:

  • –detach, -d:以后台模式运行容器。
  • –name my_container_name:为容器指定一个名称。
  • –restart always:容器退出后总是重启。
  • –volume /host/dir:/container/dir:ro:将主机的/host/dir目录以只读形式挂载到容器的/container/dir。
  • –publish 8080:80:将容器的80端口映射到主机的8080端口。
  • –env VAR1=value1:设置环境变量VAR1的值为value1。
  • –env-file ./env.list:从文件加载环境变量。
  • –memory=“512m”:限制容器内存使用为512MB。
  • –cpus=“0.5”:限制容器使用CPU核心数为0.5个核心。
  • –network my_network:连接到名为my_network的网络。
  • –mac-address=“02:42:ac:11:65:43”:指定容器的MAC地址。
  • –dns 8.8.8.8:设置DNS服务器。
  • –dns-search example.com:设置DNS搜索域名。
  • –user 1000:1000:以uid 1000 和 gid 1000的用户身份运行容器。
  • –workdir /app:设置容器的工作目录。
  • –read-only:以只读模式挂载容器的根文件系统。
  • –security-opt label=disable:禁用SELinux标签。
  • –cap-add=SYS_ADMIN:向容器添加特定能力,如SYS_ADMIN。
  • –device=/dev/sdc:向容器添加主机设备。
  • –privileged:给予容器更多权限,接近于宿主机。
  • –runtime=runc:指定容器运行时。
  • my_image:tag:使用的镜像名称及标签。
  • command arg1 arg2:容器启动后执行的命令及其参数。
docker exec [OPTIONS] CONTAINER COMMAND [ARG...]

可选参数(OPTIONS)包括:

  • -d, --detach:以后台模式运行命令,在容器中不保留标准输入输出。默认情况下,exec 命令会同步执行并等待命令完成。

  • -e, --env=[]:设置环境变量,格式为 key=value。可以多次使用该选项来设置多个环境变量。

  • -i, --interactive

    • 保持标准输入 (STDIN) 打开,即使没有连接到终端也是如此。这对于需要用户输入的交互式命令很有用。
  • -t, --tty:分配一个伪终端 (TTY),通常与 -i 一起使用,为命令提供一个类似终端的环境。

  • -u, --user=“”:指定在容器中执行命令的用户名或 UID,以及可选的组名或 GID(格式为 :)。

  • –privileged:给予在容器中运行的命令扩展权限,类似于具有 root 权限,但更进一步,能访问所有设备节点等。

  • -w, --workdir=“”:指定容器内执行命令的工作目录。

  • –detach-keys=“”:覆盖容器分离时使用的键序列。

  • –help:显示帮助信息。

  • CONTAINER 是其中执行命令的容器的名称或ID。

  • COMMAND [ARG…] 是在容器内执行的具体命令及其参数。

6. vscode插件开发

docker命令非常多,掌握最简单最常用的命令即可。推荐使用vscode和插件进入docker容器,下载docker和ssh插件:

img vscode远程连接,选择开发容器

img 选择对应的容器,进入容器内部

img

7. 总结

这里也有一份pdf文档关于docker使用,搭建了可视化的web端,使用docker-compose启动多容器(待续). 本教程目前只介绍docker构建镜像和运行容器。

up>)。

  • –privileged:给予在容器中运行的命令扩展权限,类似于具有 root 权限,但更进一步,能访问所有设备节点等。
  • -w, --workdir=“”:指定容器内执行命令的工作目录。
  • –detach-keys=“”:覆盖容器分离时使用的键序列。
  • –help:显示帮助信息。
  • CONTAINER 是其中执行命令的容器的名称或ID。
  • COMMAND [ARG…] 是在容器内执行的具体命令及其参数。

6. vscode插件开发

docker命令非常多,掌握最简单最常用的命令即可。推荐使用vscode和插件进入docker容器,下载docker和ssh插件:

[外链图片转存中…(img-pjoVEw6o-1719629496791)] vscode远程连接,选择开发容器

[外链图片转存中…(img-Orr4kovZ-1719629496792)] 选择对应的容器,进入容器内部

[外链图片转存中…(img-EWPlw53v-1719629496793)]

7. 总结

这里也有一份pdf文档关于docker使用,搭建了可视化的web端,使用docker-compose启动多容器(待续). 本教程目前只介绍docker构建镜像和运行容器。

📎docker.pdf

;