在 docker 中使用 OpenGL 和 nvidia-docker2
Posted
技术标签:
【中文标题】在 docker 中使用 OpenGL 和 nvidia-docker2【英文标题】:Using OpenGL inside docker with nvidia-docker2 【发布时间】:2019-05-16 07:07:35 【问题描述】:我正在尝试在 Ubuntu 16.04 容器内运行 OpenGL 应用程序 (Gazebo),并且我希望能够在可用时利用 nvidia 图形加速。我正在尝试找出推荐的、官方支持(希望得到 nvidia 支持)的方法是什么。
我的要求:
-
创建图像非常耗时,因此我希望为所有类型的图形(nvidia、mesa 即其他所有图像)创建一个图像,或者如果分开,它们应该“从”公共基础图像构建包含大部分内容。
nvidia 容器应该在不同的系统上工作,这些系统可能安装了不同的 nvidia 卡和驱动程序版本。
我需要使用 Ubuntu 16.04,公司需要这个,尽管这是这些要求中最不重要的,例如如果这只能在 18.04 完成,我也会感兴趣。
到目前为止我已经尝试过:
只需使用FROM nvidia/opengl:1.0-glvnd-runtime-ubuntu16.04
为 nvidia 和其他所有内容构建单独的图像。这很好用,但需要构建两个映像,这需要两倍的时间和两倍的磁盘空间。 违反了要求 1。
首先从ubuntu:16.04
构建“普通”(mesa/intel) 映像,在那里完成所有耗时的工作,然后将其用作另一个映像的基础,其中从官方“运行文件”手动安装 NVIDIA 驱动程序”。如果驱动程序与主机上安装的驱动程序完全匹配,则此方法有效,但如果主机具有不同的(例如较旧的)版本,则此方法无效。 违反了要求 2。
什么都不做,只需使用--runtime=nvidia -e NVIDIA_VISIBLE_DEVICES=all -e NVIDIA_DRIVER_CAPABILITIES=all
运行我的常规台面启用容器。如果我这样做了,nvidia-smi
会看到该卡,但 OpenGL(例如 glxinfo
)仍会尝试加载 swrast
驱动程序,这不起作用。
我在野外看到的大多数示例都使用nvidia/opengl:1.0-glvnd-runtime-ubuntu16.04
基础,而在我的一生中,我无法在该图像中找到nvidia 驱动程序的安装方式(如果有的话)。我还在某处读到,使用 nvidia 容器运行时(即我正在使用的 nvidia-docker2
)您不需要安装驱动程序,但情况似乎并非如此,至少对于 OpenGL .
再说一遍,有没有办法为 nvidia 和非 nvidia 创建满足我所有要求的容器映像,或者我只是想要太多?
【问题讨论】:
不能配置Docker从宿主环境绑定mount单个文件吗?我自己从未使用过 Docker,但经常使用 lxc 或 voidlinux 容器。本质上,您可以将外部的单个文件“绑定”到容器中。/dev
图形节点在那里很简单,所以这都是关于 OpenGL 库的(如果你想要 Vulkan,ICD)。所以我的方法是有一些辅助程序在外部确定有哪些 OpenGL / Vulkan 相关库文件,并在启动时将它们绑定到容器中。
@datenwolf 是的,我可以配置 docker 来绑定挂载单个文件,而且,nvidia-docker 已经处理好了。问题在于容器没有“看到”卡,问题在于内部有正确的驱动程序来运行 OpenGL 应用程序。
通过我提到的文件 IS 通过驱动程序。不幸的是,这些路径是特定于分布的,所以 docker 图像的分布独立性的整个想法在这里离开了舞台。但是,如果您查看ldd $(which glxinfo) | grep libGL
的输出并将那里报告的文件(确保解析符号链接!)绑定到容器中,您实际上是从外部引入了 OpenGL 驱动程序,至少对于客户端而言。对于 Vulkan,您可能需要查看 /usr/share/vulkan/icd.d
的内容
这里的要点是,Linux 中的图形驱动程序由内核部分和用户区部分组成。内核部分在所有用户空间之间共享,无论是否在容器内。用户空间部分必须匹配内核部分。并且内核驱动程序作为主机系统的一部分进行管理,因此唯一明智的方法是将主机系统的用户区部分绑定到容器中。也就是说,为什么要绑定挂载这些特定文件。
@datenwolf 是的,我知道这一点,但你基本上证实了这一点。 nvidia 容器运行时(a.k.a nvidia-docker 2.x)应该做到这一点,它确实做到了,除了显然是 OpenGL;我怀疑它主要是为 Cuda 设计的,但它确实具有可以启用的“opengl”功能。
【参考方案1】:
既然可以“窃取”别人的解决方案,为什么还要浪费时间尝试自己找出解决方案?特别是如果其他人是 NVIDIA 自己。
由于nvidia/opengl:1.0-glvnd-runtime-ubuntu16.04
似乎运作良好,但将其用作基本要求 1,我可以将文件从中复制并复制到我的图像中。
这里$from
指向我原来的、不支持nvidia 的容器映像(但我也用from=ubuntu:16.04
对其进行了测试),我只是将nvidia 的驱动程序和配置复制过来:
ARG from
FROM nvidia/opengl:1.0-glvnd-runtime-ubuntu16.04 as nvidia
FROM $from
COPY --from=nvidia /usr/local /usr/local
COPY --from=nvidia /etc/ld.so.conf.d/glvnd.conf /etc/ld.so.conf.d/glvnd.conf
ENV NVIDIA_VISIBLE_DEVICES=all NVIDIA_DRIVER_CAPABILITIES=all
有了这个,我的$from
建立在ubuntu:16.04
之上,glxinfo 返回预期的配置(NVIDIA 是 GL 供应商),我可以像在主机上一样运行 Gazebo、Blender 等。这样做的美妙之处在于,即使不使用 nvidia 运行时,生成的容器也能工作,在没有 nvidia 驱动程序的系统上,它只是优雅地回退到使用 Mesa(我猜这就是“glvnd”所做的)。
虽然我目前需要使用 Ubuntu 16.04,但我认为类似的方法不能用于其他 Ubuntu 版本。
【讨论】:
以上是关于在 docker 中使用 OpenGL 和 nvidia-docker2的主要内容,如果未能解决你的问题,请参考以下文章
如何在没有 FBConfig 错误的情况下在 docker 内运行 glut 应用程序?
在 CG 和 openGL 中使用统一的 1D 纹理参数时出错
如何在 Windows 7 中使用 OpenGL、Glut 和 Visual Studio 2008 准备 C++ 项目