这一篇单独抽出来讲讲 nspawn 容器有什么可以调优的地方
Xorg
按照 ArchWiki 的说法,必须使用只读挂载 Xorg 套接字
详情见 Wiki 的 nspawn 篇 X.org 部分
代码语言:txt复制[Files]
# Xorg
BindReadOnly =/tmp/.X11-unix
在容器中设定 $DISPLAY
变量与宿主机相同即可
GPU NVIDIA
以 ArchLinux 为例子
要想在容器内使用 N 卡,首先主机必须装好驱动
其次挂载设备肯定是逃不掉的
代码语言:txt复制[Files]
# GPU
Bind = /dev/dri
# OpenGL 与 nvidia-smi
Bind = /dev/nvidia0
Bind = /dev/nvidiactl
# OpenCL 与 CUDA
Bind = /dev/nvidia-uvm
Bind = /dev/nvidia-uvm-tools
# Vulkan
Bind = /dev/nvidia-modeset
Bind = /dev/shm
接下来安装驱动,只需要安装 lib 部分即可
代码语言:txt复制换句话说就是不要内核模块
yay -S nvidia-utils
接下来运行 nvidia-smi
会发现报错了
用 strace
跟一下发现对设备 /dev/nvidiactl
的访问被拒绝
所以我们需要用 drop-in 替换添加一些参数
在这个例子中,容器的名字为 archlinux
所以对应的服务应该是 systemd-nspawn@archlinux.service
然后我们就可以把替换文件放进
代码语言:txt复制/etc/systemd/system/systemd-nspawn@archlinux.service.d/override.conf
在替换文件里面添加 DeviceAllow
参数允许对设备文件的访问
[Service]
DeviceAllow=/dev/dri rw
DeviceAllow=/dev/shm rw
# nvidia-smi 需要
DeviceAllow=/dev/nvidiactl rw
DeviceAllow=/dev/nvidia0 rw
# OpenCL 需要
DeviceAllow=/dev/nvidia-uvm rw
DeviceAllow=/dev/nvidia-uvm-tools rw
# Vulkan 需要
DeviceAllow=/dev/nvidia-modeset rw
接下来重新加载 Systemd 服务配置
代码语言:txt复制systemctl daemon-reload
最后启动容器
代码语言:txt复制machinectl start archlinux
进去以后自己补上对应的软件包,补齐所需 lib 就完事了
音频 PulseAudio
正确挂载 D-Bus 的方法应该是将 /run/user/$UID/pulse
以 只读
的方式挂载
如果不用只读挂载,容器内很有可能清空掉这个文件夹,导致宿主机丢失 PulseAudio 套接字
从而引发所有音频失效
一个配置文件的例子如下
代码语言:txt复制[Files]
# PulseAudio
BindReadOnly=/run/user/1000/pulse
音频倒是不需要做太多的修改,挂进去就好
D-Bus
跟 PulseAudio 挂载类似,只读挂载套接字就好
如果不以只读的方式去挂载很有可能导致 nspawn 容器内将 D-Bus 套接字删得一干二净
另外虽然 /run/user/$UID
下面还有 systemd
文件夹,但是我们并不需要挂载他
为了让容器内外的 Systemd 相互通信只需要有 D-Bus 挂载就足够了
一个配置文件的例子如下
代码语言:txt复制[Files]
# AppIndicator
BindReadOnly=/run/user/1000/bus
输入法 fcitx5
容器内不需要安装 fcitx5 相关的库,但是需要保证环境变量正确设定
$XDG_RUNTIME_DIR
需要正确指向/run/user/$UID
$LANG
必须是zh_CN.UTF-8
这里应该把 $XDG_RUNTIME_DIR
指向 /run/user/1000
在实际测试中,下列程序不需要设定 XDG
变量也可以正常使用
- Chrome (含衍生版)
- Firefox
- GEdit
- GIMP
几乎所有依赖 GTK 的程序都可以正常运行
但是 Qt 程序偏偏没了就不行,经过测试的 Qt 程序如下
- QV2 某某某
- Krita
- Mumble