[ Technical exchange] 玲珑容器动态添加自定义挂载目录
Tofloor
poster avatar
MeGusta
deepin
2025-10-08 11:09
Author

linglong-container-patch.zip

到目前的玲珑版本(linglong-1.9.13)为止,玲珑容器内仍然无法访问deepin的/persistent/home,以及uos v20的/data/home。

使用起来有时会有点不方便。

通过查看 /usr/lib/linglong/container/README.md,可以了解到玲珑提供了一种通过增加配置文件,动态(生成器)或者静态(OCI配置补丁)地添加玲珑容器挂载目录的方法,两者需要放在 /usr/lib/linglong/container/config.d目录下才能生效。

1.OCI配置补丁,不可有执行权限,*.json文件,示例如下:新增挂载点:宿主机/opt/apps 挂载到容器内/opt/host-apps。

需要注意的是,如果把配置文件放在 /usr/lib/linglong/container/config.d下,是全局设置,对所有玲珑应用生效,

如果把配置文件放在 /usr/lib/linglong/container/config.d/$LINGLONG_APPID目录下,则仅对玲珑应用ID为 $LINGLONG_APPID的容器生效。

{
  "ociVersion": "1.0.1",
  "patch": [
    {
      "op": "add",
      "path": "/mounts/-",
      "value": {
        "destination": "/opt/host-apps/",
        "type": "bind",
        "source": "/opt/apps",
        "options": [
          "rbind"
        ]
      }
    }
  ]
}

2.生成器:

是一个可执行文件,需要有执行权限,可以根据宿主环境动态生成挂载配置。

由于deepin与uos v20需要额外挂载的目录不同,前者是/persistent/home,后者是/data/home,我需要动态地调整挂载配置,所以就采用这种方法。

把说明文件和需求扔给AI,就可以得到我所需要的生成器,然后按照全局或者局部生效的规则,放到不同的目录中去。

#!/bin/sh
# generator: 99-bind-home.sh
# 作用:
# - 若宿主机存在 /persistent/home → 挂载到容器 /persistent/home
# - 若宿主机存在 /data/home → 挂载到容器 /data/home
# - 防重复挂载

set -e

# 从 stdin 读取原始 OCI 配置
CONFIG=$(cat -)

# jq 辅助函数:检测是否已经存在挂载
has_mount() {
    DEST="$1"
    echo "$CONFIG" | jq -e --arg dest "$DEST" '.mounts // [] | map(.destination) | index($dest)' >/dev/null 2>&1
}

# jq 构造挂载对象
create_mount() {
    DEST="$1"
    SRC="$2"
    jq -n --arg dest "$DEST" --arg src "$SRC" '{
        destination: $dest,
        type: "bind",
        source: $src,
        options: ["rbind"]
    }'
}

# 挂载数组初始化为空
NEW_MOUNTS="[]"

# 条件挂载宿主机目录
[ -d "/persistent/home" ] && ! has_mount "/persistent/home" && \
    NEW_MOUNTS=$(echo "$NEW_MOUNTS" | jq --argjson m "$(create_mount /persistent/home /persistent/home)" '. + [$m]')

[ -d "/data/home" ] && ! has_mount "/data/home" && \
    NEW_MOUNTS=$(echo "$NEW_MOUNTS" | jq --argjson m "$(create_mount /data/home /data/home)" '. + [$m]')

# 如果没有新增挂载,直接输出原配置
[ "$(echo "$NEW_MOUNTS" | jq 'length')" -eq 0 ] && { echo "$CONFIG"; exit 0; }

# 合并到原配置的 mounts 数组中
CONFIG=$(echo "$CONFIG" | jq --argjson new_mounts "$NEW_MOUNTS" '
    .mounts = (.mounts // []) + $new_mounts
')

# 输出修改后的完整 OCI 配置
echo "$CONFIG"

3.在deepin25中的使用,由于/usr不可写,就需要生成deb包来传入系统中去,以下是构建deb安装包的两个脚本,前者是全局生效,后者是局部生效:

全局生效:

#!/usr/bin/env bash

# make-deb-global.sh
# 作用:
# - 生成全局生效的玲珑配置deb安装包

set -e

# 检查 jq
if ! command -v jq >/dev/null 2>&1; then
    echo "❌ jq 未安装,请先安装 jq (sudo apt install jq)"
    exit 1
fi

# 配置文件的名称
GENERATOR="99-bind-home.sh"

HERE="$(cd "$(dirname "$0")" && pwd)"
PKGNAME="linglong-container-patch-global"
VERSION="1.0-1"
ARCH="all"
BUILD_DIR="$HERE/${PKGNAME}_build"
GENERATOR_PATH="$HERE/$GENERATOR"

# 若变量不存在则设定默认值
: "${DEBEMAIL:=Jetcser@gmail.com}"
: "${DEBFULLNAME:=MeGusta}"

# 临时构建目录
mkdir -p "$BUILD_DIR/DEBIAN"
chmod 0755 "$BUILD_DIR/DEBIAN"
mkdir -p "$BUILD_DIR/usr/lib/linglong/container/config.d"

# 复制 generator
chmod +x "$GENERATOR_PATH"
cp -a "$GENERATOR_PATH" "$BUILD_DIR/usr/lib/linglong/container/config.d/$GENERATOR"

# 生成 control 文件,增加依赖 jq
cat > "$BUILD_DIR/DEBIAN/control" <
Depends: jq
Description: Linglong container patch globally.
 This package installs a custom generator for Linglong container config.
EOF

# 构建 deb 包
dpkg-deb --build "$BUILD_DIR" "${PKGNAME}_${VERSION}_${ARCH}.deb"

# 清理临时文件
rm -rf "$BUILD_DIR"

echo "✅ 构建完成: $(realpath "${PKGNAME}_${VERSION}_${ARCH}.deb")"

局部生效:

#!/usr/bin/env bash

# make-deb.sh
# 作用:
# - 生成对特定玲珑容器生效的玲珑配置deb安装包

set -e

# 检查 jq
if ! command -v jq >/dev/null 2>&1; then
    echo "❌ jq 未安装,请先安装 jq (sudo apt install jq)"
    exit 1
fi

# 检查参数
if [ -z "$1" ]; then
    echo "用法: $0 "
    exit 1
fi

# 配置文件的名称
GENERATOR="99-bind-home.sh"

LINGLONG_APPID="$1"
HERE="$(cd "$(dirname "$0")" && pwd)"
PKGNAME="linglong-container-patch-$LINGLONG_APPID"
VERSION="1.0-1"
ARCH="all"
BUILD_DIR="$HERE/${PKGNAME}_build"
GENERATOR_PATH="$HERE/$GENERATOR"

# 若变量不存在则设定默认值
: "${DEBEMAIL:=Jetcser@gmail.com}"
: "${DEBFULLNAME:=MeGusta}"

# 临时构建目录
mkdir -p "$BUILD_DIR/DEBIAN"
chmod 0755 "$BUILD_DIR/DEBIAN"
mkdir -p "$BUILD_DIR/usr/lib/linglong/container/config.d/$LINGLONG_APPID"

# 复制 generator
chmod +x "$GENERATOR_PATH"
cp -a "$GENERATOR_PATH" "$BUILD_DIR/usr/lib/linglong/container/config.d/$LINGLONG_APPID/$GENERATOR"

# 生成 control 文件,增加依赖 jq
cat > "$BUILD_DIR/DEBIAN/control" <
Depends: jq
Description: Linglong container patch for appid $LINGLONG_APPID
 This package installs a custom generator for Linglong container config.
EOF

# 构建 deb 包
dpkg-deb --build "$BUILD_DIR" "${PKGNAME}_${VERSION}_${ARCH}.deb"

# 清理临时文件
rm -rf "$BUILD_DIR"

echo "✅ 构建完成: $(realpath "${PKGNAME}_${VERSION}_${ARCH}.deb")"

Reply Favorite View the author
All Replies
Feelup
deepin
2025-10-08 14:33
#1

真棒

kissing_heart

Reply View the author
兆兆嘟嘟嘟
deepin
Q&A Team
2025-10-08 15:11
#2

感谢分享。

Reply View the author
罐子
deepin
2025-10-08 17:37
#3
{
  "ociVersion": "1.0.1",
  "patch": [
    {
      "op": "add",
      "path": "/mounts/-",
      "value": {
        "destination": "/opt/extensions/org.deepin.driver.display.nvidia.570-124-04",
        "type": "bind",
        "source": "/var/lib/linglong/layers/bfdfac1726a019a3c87d31a405e11bd6c96129a92159c2f52d12efdf116487f6/files",
        "options": ["rbind","ro","rslave","nosuid","nodev"]
      }
    },

    { "op": "add", "path": "/process/env/-", "value": "__NV_PRIME_RENDER_OFFLOAD=1" },
    { "op": "add", "path": "/process/env/-", "value": "__GLX_VENDOR_LIBRARY_NAME=nvidia" },
    { "op": "add", "path": "/process/env/-", "value": "__EGL_VENDOR_LIBRARY_DIRS=/opt/extensions/org.deepin.driver.display.nvidia.570-124-04/glvnd/egl_vendor.d:$ORIGIN" },
    { "op": "add", "path": "/process/env/-", "value": "__EGL_EXTERNAL_PLATFORM_CONFIG_DIRS=/opt/extensions/org.deepin.driver.display.nvidia.570-124-04/egl/egl_external_platform.d" },
    { "op": "add", "path": "/process/env/-", "value": "VK_ICD_FILENAMES=/opt/extensions/org.deepin.driver.display.nvidia.570-124-04/vulkan/icd.d/nvidia_icd.json" },

    { "op": "add", "path": "/process/env/-", "value": "LD_LIBRARY_PATH=/opt/extensions/org.deepin.driver.display.nvidia.570-124-04/orig:/usr/lib/x86_64-linux-gnu:/usr/lib" }
  ]
}

@MeGusta 给你个显卡的

Reply View the author
MeGusta
deepin
2025-10-08 20:19
#4
罐子
{
  "ociVersion": "1.0.1",
  "patch": [
    {
      "op": "add",
      "path": "/mounts/-",
      "value": {
        "destination": "/opt/extensions/org.deepin.driver.display.nvidia.570-124-04",
        "type": "bind",
        "source": "/var/lib/linglong/layers/bfdfac1726a019a3c87d31a405e11bd6c96129a92159c2f52d12efdf116487f6/files",
        "options": ["rbind","ro","rslave","nosuid","nodev"]
      }
    },

    { "op": "add", "path": "/process/env/-", "value": "__NV_PRIME_RENDER_OFFLOAD=1" },
    { "op": "add", "path": "/process/env/-", "value": "__GLX_VENDOR_LIBRARY_NAME=nvidia" },
    { "op": "add", "path": "/process/env/-", "value": "__EGL_VENDOR_LIBRARY_DIRS=/opt/extensions/org.deepin.driver.display.nvidia.570-124-04/glvnd/egl_vendor.d:$ORIGIN" },
    { "op": "add", "path": "/process/env/-", "value": "__EGL_EXTERNAL_PLATFORM_CONFIG_DIRS=/opt/extensions/org.deepin.driver.display.nvidia.570-124-04/egl/egl_external_platform.d" },
    { "op": "add", "path": "/process/env/-", "value": "VK_ICD_FILENAMES=/opt/extensions/org.deepin.driver.display.nvidia.570-124-04/vulkan/icd.d/nvidia_icd.json" },

    { "op": "add", "path": "/process/env/-", "value": "LD_LIBRARY_PATH=/opt/extensions/org.deepin.driver.display.nvidia.570-124-04/orig:/usr/lib/x86_64-linux-gnu:/usr/lib" }
  ]
}

@MeGusta 给你个显卡的

好的,谢谢~我回去试试看看效果明显不

Reply View the author
罐子
deepin
2025-10-08 21:11
#5
sudo ll-cli install org.deepin.driver.display.nvidia.570-124-04

记得安装这个,还要确保宿主机有安装显卡内核驱动

cat /sys/module/nvidia/version

这里的版本一致的话就会自动加载扩展

Reply View the author