Axi's Blog

Back

Isaac Sim 一百讲(a):Docker 使用Blur image

前言#

Docker 是一个很强大的工具,可以快速地搭建一个开发环境,并且可以很方便地进行迁移,然而我们本不需要 Docker 来使用 Isaac Sim。假如说读者只需要在自己的电脑上使用 Isaac Sim,那么完全不需要 Docker,自己的电脑只有一张显卡,正常运行也不会有任何的问题。

然而假如说在服务器上使用的时候,尤其是指多卡的服务器上,只要进行了简单的尝试,读者就会很快发现问题所在:Isaac Sim 并不会识别 CUDA Visible Devices,而是会默认使用所有可见的 GPU。Isaac Sim 的显卡占用策略并不是合理的,对于一个需要 6GB 显存的应用,假如说有 8 张显卡,那么 Isaac Sim 会占用 8 张显卡上面各 5GB,这毫无疑问的巨大的浪费。

上手 Docker#

解决方法也很简单,使用 Docker 即可。对于大多数读者来说,可能都是久仰 Docker 的大名,然而对于如何使用,以及如何最快速地上手依然心存疑虑,事实证明 Docker 并非十分复杂,在你的 Isaac Sim 之旅中,也不需要过多的 Docker 知识。

首先,在这里指路 Isaac Sim 的文档:

首先你需要通过正常的 APT 方法安装 Docker 以及 CUDA 的 Toolkit,前者让你可以使用 Docker,后者则可以让你使用 GPU。

安装 Docker:

# Docker installation using the convenience script
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

# Post-install steps for Docker
sudo groupadd docker
sudo usermod -aG docker $USER
newgrp docker

# Verify Docker
docker run hello-world
bash

这其中你需要注意的是,假如说你的设备上已经安装了 Docker,那么你唯一需要进行的操作就是让管理员给你添加到 Docker 用户组里面,即:

sudo usermod -aG docker $USER
bash

接下来安装 CUDA 的 Toolkit:

# Configure the repository
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \
  && curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
    sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
    sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list \
  && \
    sudo apt-get update

# Install the NVIDIA Container Toolkit packages
sudo apt-get install -y nvidia-container-toolkit
sudo systemctl restart docker

# Configure the container runtime
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker

# Verify NVIDIA Container Toolkit
docker run --rm --runtime=nvidia --gpus all ubuntu nvidia-smi
bash

当然,事实上这些 Docker 的 run 的指令你都没必要跑。

使用 Isaac Sim Docker#

首先你需要下载 Isaac Sim 的 Docker,这是一个很简单的操作:

docker pull nvcr.io/nvidia/isaac-sim:4.1.0
bash

但是紧接着,在大多数服务器上,你会发现问题,即网络问题导致你无法进行访问。服务器的一些设置使得你添加了代理之后也难以获取这些 Docker,因此你只能手动将文件上传。

手动上传#

首先,你需要下载 Isaac Sim 的 Docker 文件:

docker pull nvcr.io/nvidia/isaac-sim:4.1.0
bash

这一步操作发生在你个人的电脑上,并且使用了代理。

使用 docker images 查看你本地的 Docker 镜像,然后使用 docker save -o isaac-sim-4.1.0.tar <image_id> 将镜像保存为 tar 文件。

之后可以通过 sftp 或者 scp 将文件上传到服务器上。在服务器上,使用 docker load -i isaac-sim-4.1.0.tar 将镜像加载到本地。

然后你就可以使用:

docker run --name isaac-sim --entrypoint bash -it --runtime=nvidia --gpus all -e "ACCEPT_EULA=Y" --rm --network=host \
    -e "PRIVACY_CONSENT=Y" \
    -v ~/docker/isaac-sim/cache/kit:/isaac-sim/kit/cache:rw \
    -v ~/docker/isaac-sim/cache/ov:/root/.cache/ov:rw \
    -v ~/docker/isaac-sim/cache/pip:/root/.cache/pip:rw \
    -v ~/docker/isaac-sim/cache/glcache:/root/.cache/nvidia/GLCache:rw \
    -v ~/docker/isaac-sim/cache/computecache:/root/.nv/ComputeCache:rw \
    -v ~/docker/isaac-sim/logs:/root/.nvidia-omniverse/logs:rw \
    -v ~/docker/isaac-sim/data:/root/.local/share/ov/data:rw \
    -v ~/docker/isaac-sim/documents:/root/Documents:rw \
    nvcr.io/nvidia/isaac-sim:4.1.0
bash

Docker 快速上手#

Docker 的基本使用#

你可以看着上面的东西会想,wait,发生了什么,这些指令都是什么意思,这很正常,让我娓娓道来。

本身,你可以这样理解,Docker 这个工具是让你运行一个封闭的小型的 Linux 系统,这个系统里面有你需要的所有东西,你只需要在上面运行你的程序即可。这种感觉实际上很像我们常用的 miniconda,而事实上我们也可以用类似的思路去使用一些 Docker 镜像。

镜像和容器是 Docker 两个十分重要的内容,镜像是某种系统,而容器则是一个实例,使得这个系统正在运行。假如说你想要修改镜像,一个显然的操作是,运行一个实例,然后修改,然后保存为新的镜像。

使用 docker images 可以查看你本地的镜像,使用 docker ps -a 可以查看你的容器。假如说你退出了容器,一种可能的结果是这个容器就会停止,但是你依然可以重新启动它。

使用 docker run 可以运行一个容器,在我们的例子中,这个容器来自本地,通过你之前的 load 操作进行了加载,可以在 docker images 中看到,并且可以运行。

Docker 参数#

理解了 Docker 的运行发生了什么,让我们来理解一下这些参数。我们可以交互式地运行一个容器,也可以直接让容器运行固定的指令,跑在后台,假如说你还是不是很熟悉 Docker 的运行方式,那么你或许可以尝试一下交互的运行,这样你可以直接把 Docker 当作某个服务器去使用,这种感觉一模一样,使用 -it 即可。而相对应的,使用 -d 则可以让容器在后台运行。

--rm 来自于另一个简单的需求,在我运行完了这个容器,容器结束了之后,我希望其可以直接销毁,这样我就不用每次都手动去删除容器了。不过在这里依然介绍一下手动销毁的方式,使用 docker rm <container_name> 即可。对于全部的容器,你需要先使得其停止,才能销毁,即 docker stop <container_name>,你可以在 docker ps -a 中看到全部的容器,并且了解他们是否还在运行。

另一个常见的需求是使用 -v 挂载卷,即挂载一个本地的目录到容器中,这样你就可以在容器中修改文件,并且修改会自动同步到本地。这种操作同样可以反过来,我有若干个容器都在使用同一个卷,那么我就可以在本地修改,这个修改会被反馈到全部的容器中。前者可以用于生产数据,后者可以用于共享代码。

--entrypoint 则可以让你指定容器运行的入口点,即容器运行的第一个命令,Isaac Sim 官方的容器默认会执行 ./python.sh,直接启动一个 Isaac Sim 程序,而我们现在只是想进去逛逛,于是设置为 bash,顶替了默认的入口点,使得可以以正常的命令行方式进入。

-e 则可以让你指定环境变量,这里我们使用到了 ACCEPT_EULAPRIVACY_CONSENT,这两个变量分别表示你已经阅读并同意了 NVIDIA 的 EULA 和 Privacy Policy。

--gpus 则可以让你指定容器运行的 GPU,这里我们使用到了全部的 GPU,即 all,假如说你想要指定一张特定的卡,那么你可以使用 --gpus "device=0" 来指定第 0 张卡。

编辑你的 Docker 镜像#

于是我们也就不难实际上手了,运行之前提及的指令,不过你可以不需要挂那些文件,这并非你的需求,同时删除 --rm 参数,这样你退出之后就可以保留容器,并且进行 docker commit 操作了。

docker run --name isaac-sim --entrypoint bash -it --runtime=nvidia --gpus 1 -e "ACCEPT_EULA=Y" --network=host -e "PRIVACY_CONSENT=Y" nvcr.io/nvidia/isaac-sim:4.1.0
bash

同时你可以注意到,我们分配了一张卡,即 --gpus 1,这里的 1 是数量,而非编号。

运行完这个指令之后,你不难发现,你进入了 /isaac-sim 目录,并且处于命令行界面。你可以使用 ctrl+d 退出。

使用 docker commit <container_name> <image_name> 即可将容器保存为镜像。你可以通过之前提及的 docker ps -a 来查看你的容器名称。

在你进行了这一次保存之后,我们姑且认为这个镜像叫做 isaac,那么你可以直接运行:

docker run -it --gpus 1 isaac
bash

此时你又一次进入了命令行中。你可以尝试给这个环境安装一些库,比如:

./python.sh -m pip install open3d
bash

然后再次执行你的 commit 流程,你就可以得到一个包含 open3d 的镜像。

Isaac Sim Docker 的一种运行逻辑#

你现在已经可以使用 Isaac Sim 了,执行一些程序也不是很难,事实上有一种文件拷贝的方式,你可以通过 docker cp 将文件拷贝到容器中,然后运行。

docker cp <file_path> <container_name>:/path/to/destination
bash

然而这很麻烦,你最后会维护一个巨大的容器,每一次修改文件,你都需要进入容器,修改并且 commit。

事实上,你完全可以使用 Docker 的卷挂载,将你的项目挂载到容器中,这样你就可以在容器中修改文件,并且修改会自动同步到本地,这个感觉很像一个大号的 miniconda。

我们假设这样一个场景,你有一个项目想要用来生成数据,因此你有了三个文件夹:

  • data 用来存放数据
  • code 用来存放代码
  • scenes 用来存放场景

你想要在容器中运行这个项目,那么你只需要:

docker run -it --gpus 1 --name isaac-1 --gpus 1\
        -v ~/docker/isaac-sim/data:/isaac-sim/data \
        -v ~/docker/isaac-sim/code:/isaac-sim/code \
        -v ~/docker/isaac-sim/scenes:/isaac-sim/scenes \
        isaac ./python.sh code/main.py
bash

之后比如说你在 code 中修改了代码,你不需要进入容器,你只需要在本地修改,然后容器就会自动同步,因为他们是同一个文件。

然后再次执行上述的指令即可。

总结#

对于在服务器上运行 Isaac Sim 的读者来说,使用 Docker 显然是一个必须掌握的技巧,本内容中我们介绍了如何使用 Docker 来运行 Isaac Sim,并且介绍了如何使用 Docker 来编辑你的镜像,以及如何使用 Docker 来挂载卷。通过我们讲解的运行逻辑,你可以把 docker 当作一个 miniconda 来使用,本身你执行的指令 ./python.sh code/main.py,只是在其前面加了一大堆的前缀而已,符合大多数读者常见的使用逻辑。

Isaac Sim 一百讲(a):Docker 使用
https://axi404.top/blog/isaac-docker
Author 阿汐
Published at January 23, 2025
Comment seems to stuck. Try to refresh?✨