跳转到内容

挂载点与 bind mount ​

容器除了根文件系统,经常还需要额外的存储空间,或者访问宿主机上已有的一个目录(最常见的是媒体库、下载目录)。PVE 用 mp0–mp255 这一组配置项统一处理,但背后其实是两种完全不同的机制,代价也不一样。

移除挂载点可能连数据一起删掉

存储支持的卷挂载点(比如放在 ZFS 或 LVM-Thin 上的那种),在 Web UI 里点 Remove 不只是解除引用,而是连底层存储卷一起销毁。

影响范围:这个挂载点对应的整块存储卷,数据不可恢复(除非有独立备份)。

前置条件:动手前确认这不是你还需要的数据,且已有独立备份(不是同一个池上的快照)。

怎么回退:没有回退。误删之前唯一的保障是备份,见备份与恢复。

bind mount 不在此列:bind mount 的 Remove 只是解除容器和宿主机目录的关联,不会删除宿主机上的源文件,两种机制混着用时容易搞混,动手前先分清这个挂载点是哪一种。

为什么需要弄清楚这两种机制 ​

  • 存储支持的挂载点:PVE 在某个存储上分配一块新的卷(磁盘镜像或 ZFS 子卷),当作容器的一个目录挂进去。它被 PVE 存储层管理,能参与备份、能设配额。
  • Bind mount:直接把宿主机上已经存在的一个目录,映射进容器的某个路径。它绕开了 PVE 的存储管理,好处是简单直接(比如共享宿主机的媒体库),代价是拿不到存储层的能力。

搞混这两种,最常见的后果是「以为 bind mount 的目录会被备份,结果 vzdump 根本没管它」,或者「删挂载点的时候把数据一起删了」。

开始之前 ​

操作步骤 ​

做法一:存储支持的挂载点(新分配一块空间) ​

Web UI:容器 → Resources → Add → Mount Point,或命令行:

sh
# 在宿主机 shell 执行
# thin1 是存储 ID,10 是容量(GiB),/data 是容器内路径
pct set <ctid> -mp0 thin1:10,mp=/data

常用可选参数:

参数作用
backup=<1|0>是否参与 vzdump 备份,默认参与
ro=<1|0>挂载为只读
quota=<1|0>启用用户配额(需要 ext4 镜像 + 特权容器,多数环境用不上)
replicate=<1|0>是否参与存储复制
acl=<1|0>显式开关 ACL 支持

做法二:Bind mount(挂载宿主机已有目录) ​

sh
# 在宿主机 shell 执行
pct set <ctid> -mp0 /mnt/bindmounts/shared,mp=/shared

Bind mount 的几条硬规则

  • 源路径不能包含符号链接,出于安全考虑。
  • 官方文档建议把要 bind mount 的目录集中放在一个专门的目录下(例如 /mnt/bindmounts/),不要直接 bind mount /、/var、/etc 这类系统目录——容器如果被攻破,能直接反过来影响宿主机。
  • vzdump 完全不备份 bind mount 的内容。这部分数据要么本来就在别处有备份,要么需要单独设计备份方式。

处理非特权容器的权限问题 ​

Bind mount 一个宿主机目录后,容器里经常看到属主是 nobody:nogroup,写入被拒绝。原因和解决方法见特权与非特权容器——核心公式是宿主机 UID = 100000 + 容器内 UID,最简单的办法是把宿主机目录属主改成映射后的 UID。

也可以在挂载点级别单独覆盖映射,不影响容器其他部分:

sh
# mp0 覆盖为:容器内 UID 0 对应宿主机 UID 1000,映射 1 个 ID
pct set <ctid> -mp0 /mnt/bindmounts/shared,mp=/shared,idmap=u:0:1000:1

idmap 的格式是 类型:容器内起始:宿主机起始:范围(u 表示 UID,g 表示 GID),只对这一个挂载点生效,比调整 lxc.idmap 影响面更可控,但同样要小心配置,配错的表现通常是这个挂载点在容器里完全看不到或者权限依旧不对。

设备挂载点(较少用) ​

还有一种直接挂载宿主机块设备的用法,同样不受存储层管理,vzdump 不会备份,只用于特殊场景(比如把整块盘映射进容器),日常使用中优先考虑前两种。

检查结果 ​

  1. pct config <ctid> 里能看到对应的 mp0(或其他编号)行,字段符合预期。
  2. 容器内确认挂载生效并且能写入:
sh
# 在容器内部执行
df -h
touch /data/test-file && ls -l /data/
  1. 存储支持的挂载点:到 Web UI 存储视图确认对应的卷已创建。
  2. Bind mount:确认宿主机源目录和容器内看到的内容一致,属主不是 nobody。
  3. 需要备份的挂载点,跑一次 vzdump 测试,确认这个挂载点确实包含在了备份里(backup=1 的存储卷会;bind mount 不会,需要单独处理)。

常见问题 ​

容器里看到目录属主是 nobody:nogroup,写入被拒绝。 典型的非特权容器 UID 映射问题,按上文「宿主机 UID = 100000 + 容器内 UID」的公式改宿主机目录属主,或者用 idmap 参数覆盖,见特权与非特权容器。不要因为这个问题就把容器改成特权容器——那是放弃整个隔离机制去换权限方便,代价和收益完全不对等。

备份完成之后发现 bind mount 的数据没有被备份进去。 这是设计如此,不是故障。vzdump 只处理存储管理的卷,bind mount 的数据要么本来就在别的地方有备份(比如它本身就是另一个存储池),要么需要你单独安排备份方式。

想在容器里跑 FUSE 文件系统当挂载点。 官方文档明确不建议在容器内部使用 FUSE 挂载,容易和 freezer 子系统(快照、挂起时用到)冲突。正确做法是在宿主机上完成 FUSE 挂载,再把挂载后的结果 bind mount 进容器。

Quota 选项开了不生效。 配额功能需要 ext4 镜像存储且是特权容器;纯 cgroup v2(PVE 9 默认)环境下这条路径本身受限,多数场景不必强求配额,改用资源限制或者独立卷更省事。

参考资料 ​

延伸阅读 ​

Proxmox VE 非官方中文使用指南,与 Proxmox Server Solutions GmbH 无隶属关系。