LOADING...

加载过慢请开启缓存(浏览器默认开启)

loading

LXD 桌面化

桌面化,就是使容器的 GUI 应用能直接使用主机的 Xorg。

Subuid/Subgid

编辑 /etc/subuid 文件,${user_uid} 为 当前用户的 uid:

lxd:${user_uid}:1
root:${user_uid}:1
lxd:1000000:65536
root:1000000:65536

编辑 /etc/subgid 文件,${video_gid}${audio_gid} 分别是 video 和 audio 组的 gid:

lxd:${video_gid}:1
root:${video_gid}:1
lxd:${audio_gid}:1
root:${audio_gid}:1
lxd:${user_uid}:1
root:${user_uid}:1
lxd:1000000:65536
root:1000000:65536

LXD 为容器映射,这一步是需要 restart 容器的:

echo -e "both ${user_uid} ${user_uid}\ngid ${video_gid} ${video_gid}\ngid ${audio_gid} ${audio_gid}" | lxc config set $container_name raw.idmap -

生成的配置用 lxc config show $container_name 查看,类似:

config:
  ...
  raw.idmap: |
    both ${user_uid} ${user_uid}
	gid ${video_gid} ${video_gid}
  ...

User

在容器一端创建 uid 一样的用户,保持 video 和 audio 组一样的 gid:

lxc exec $container_name -- bash
useradd -m -u $user_uid $user_name
sed -ri 's/^(video|audio)/# \1/' /etc/group
echo "video:x:$video_gid:" >> /etc/group
echo "audio:x:$audio_gid:" >> /etc/group
gpasswd -a $user_name video
gpasswd -a $user_name audio
exit

根据不同发行版和 Shell 确定该用户的默认 profile,如 ~/.profile 或者 ~/.bash_profile,后续的环境变量全部写入其中。

Dbus(可选)

Dbus 的支持是为了像全局菜单(容器内也必须安装 libdbusmenu 类的包)能作用于容器的 GUI 应用,非是必须的。

Systemd 默认将用户的 dbus 位置是 /run/user/$user_uid/bus,但是容器里的 /run/user/$user_uid 是变动的,所以不能直接按照相同路径映射,即使容器也是基于 Systemd 的。所以要将 dbus 映射到一个固定的地方:

lxc config device add "$container_name" \
    socket_dbus \
    proxy \
    bind=container \
    uid=$user_uid \
    gid=$user_uid \
    security.uid=$user_uid \
    security.gid=$user_uid \
    mode="0777" \
    connect=unix:/run/user/$user_uid/bus \
    listen=unix:/home/$user_name/.bus

在容器里头写入环境变量:

lxc exec $container_name -- bash
echo "export DBUS_SESSION_BUS_ADDRESS=unix:path=/$HOME/.bus" >> $profile_file
exit

PulseAudio(可选)

同 Dbus 一样,Systemd 默认将用户的 pulse 的 socket 放到 /run/user/$user_uid/pulse/native

lxc config device add "$container_name" \
    socket_pulse \
    proxy \
    bind=container \
    uid=$user_uid \
    gid=$user_uid \
    security.uid=$user_uid \
    security.gid=$user_uid \
    mode="0777" \
    connect=unix:/run/user/$user_uid/pulse/native \
    listen=unix:/home/$user_name/.pulse-native

在容器里头写入环境变量,关闭 pulse 共享内存:

lxc exec $container_name -- bash
echo "export PULSE_SERVER=$HOME/.pulse-native" >> $profile_file
sed -i "s/; enable-shm = yes/enable-shm = no/g" /etc/pulse/client.conf
exit

GPU

LXD 已经简化了对于 gpu 设备的映射,只需要:

lxc config device add "$container_name" \
    device_gpu \
    gpu \
    uid=$user_uid \
    gid=$user_gid

当然了,如果是诸如驱动带有功能的,如 Nvidia Driver 带的 smi 工具集的,有三种办法:

  1. 自己手动找到所有主机的文件去映射,由于文件多且变数大,所以不妥
  2. 容器直接也跟主机一样直接安装驱动,但是必须一直保持版本一致,稍显麻烦
  3. 由 Nvidia 提供的 nvidia-container-toolkit 项目,但是 LXD 下还有些问题

最简单是方案二,但是考虑多容器和主机的更迭,方案三是比较妥当的。安装完 nvidia-container-toolkit 和 libnvidia-container 后,需要让 /dev/nvidia 的权限是 666 (不建议)或者允许 root 来执行 nvidia-container-cli configure(修改 /usr/share/lxc/hooks/nvidia 里的全局参数为 global_args+=(--user=root:video)),然后 LXD 配置对 Nvidia 的支持:

lxc config $container_name set nvidia.runtime true
lxc config $container_name set nvidia.driver.capabilities all

Xorg

将主机 Xorg 的 socket 给 容器:

lxc config device add "$container_name" \
    socket_xorg \
    proxy \
    bind=container \
    security.uid=$user_uid \
    security.gid=$user_gid \
    connect=unix:@/tmp/.X11-unix/X0 \
    listen=unix:@/tmp/.X11-unix/X0

LXD 在映射设备的时候,可以在路径前面加 @ 代表是抽象 socket,没有物理地址,加载在内存的。

在容器里头写入环境变量:

lxc exec $container_name -- bash
echo "export DISPLAY=$HOST_DISPLAY" >> $profile_file
exit

如果主机是带有 xauth,可以有两种方式去连接 Xorg:

  1. 主机安装 xhost,然后执行 xhost +local:
  2. 修改主机 $XAUTHORITY 文件,然后将文件传到容器里,并写入容器环境变量中

主题样式(可选)

容器可以有自己的主题样式,例如主机是 Plasma Breeze 主题,想让容器的主题也保持一致可以:

lxc exec my-debian-container -- bash
apt install -y breeze breeze-gtk-theme
cat << EOF >> ~/.profile
export QT_STYLE_OVERRIDE=Breeze
EOF
exit

同样 QT 界面可以根据不同桌面显示情况配置的环境变量还有:

export QT_X11_NO_MITSHM=1
export QT_SCALE_FACTOR=1
export QT_AUTO_SCREEN_SCALE_FACTOR=0
export QT_SCREEN_SCALE_FACTORS=2

中文(可选)

容器的需要有 zh_CNlocale.gen,可以参考 Linux 基础配置

输入法像 fctix,跟主机一样,容器内对于 gtk 和 qt 都需对应的 so。所以需要在容器内安装 fcitx-qt 和 fcitx-gtk,并设置环境变量:

lxc exec my-debian-container -- bash
apt install -y fcitx5-frontend-qt5 fcitx-frontend-qt5 fcitx5-frontend-gtk2 fcitx5-frontend-gtk3
cat << EOF >> ~/.profile
export LC_CTYPE=zh_CN.utf8  
export XMODIFIERS="@im=fcitx"  
export XIM=fcitx  
export XIM_PROGRAM=fcitx  
export GTK_IM_MODULE=fcitx  
export QT_IM_MODULE=fcitx
EOF
exit