DEBUG.WIKI
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国
雨云;给项目一台云服务器
RackNerd;$21.99/年 · 1GB KVM

Docker 容器启动后,宿主机新挂载的 USB 目录仍显示为空

Linux Docker bind mount 默认 rprivate,不会接收后来创建的子挂载。核对宿主机 shared 条件,再选择 rslave 单向传播或先挂载后创建容器。

宿主机先启动容器,再把 USB 设备挂到 /media/usb:宿主机能看到文件,容器里的同名目录却是空的。若先完成设备挂载、再创建容器就能看到内容,应区分“目录内新增文件”和“在目录下新增一个挂载点”。它们不是同一种变化。

本文针对原生 Linux Docker Engine 的 bind mount,设备解锁和挂载已由宿主机完成。Docker Desktop 不支持这里讨论的挂载传播;命名卷也不能按相同方式设置传播模式。不需要为了让容器读取宿主机已经挂好的文件系统,就把它改成特权容器。

rprivate 不接收后来出现的子挂载

Docker 的 bind mount 默认使用 rprivate。已绑定目录中的普通文件变化通常可以被两侧读取,但后来创建的子挂载不会因此自动传播进去。容器可能仍看到挂载点底下原来的空目录。

创建容器时已经存在的子挂载,默认会随递归绑定一起包含进来,所以“先挂载再创建”能看到,而相反顺序看不到。这不表示 Docker 正在缓慢同步文件,也不能仅凭目录为空就判定文件权限错误。

如果宿主机和容器都已经指向同一个子挂载,但读取报 Permission denied,则需另查访问权限。传播配置不能修复普通文件的属主、权限或应用路径错误。

核对实际绑定和宿主机传播状态

media-reader 是示例容器名,源目录和子目录需要按实际替换。先在连接正确 Engine 的终端读取:

docker inspect --type container --format '{{json .Mounts}}' media-reader

确认对应记录是 Type=bind,Source、Destination 正确,并查看 Propagation 是否为 rprivate。Source 属于 daemon 所在机器;远程 Docker 的挂载检查应在那台 Linux 宿主机进行。

宿主机有 util-linux findmnt 时,可分别检查父路径与已经挂好的子路径:

findmnt --target /media --output TARGET,SOURCE,FSTYPE,PROPAGATION
findmnt --target /media/usb --output TARGET,SOURCE,FSTYPE,PROPAGATION

--target 查找包含指定路径的文件系统,不要求该路径本身就是独立挂载点。两条输出可以帮助确认子路径是否真的进入了另一个挂载,以及父级挂载是否具备 shared 传播条件。

如果父级是 private,仅给容器加 rslave 不能凭空建立来自宿主机的传播链。不要为此直接把整个 / 改成 rshared。更稳妥的短期路径是先在宿主机完成所需挂载,再按原部署配置创建目标容器;长期需要动态接收子挂载时,应先由宿主机挂载配置为专用目录建立明确的 shared 父挂载。

只需要宿主机传入时选择 rslave

在宿主机父挂载已经满足 shared 条件的前提下,把目标 bind mount 的传播模式改为 rslave。它接收宿主机向下传播的挂载变化,不把容器内创建的挂载反向传播给宿主机。

下面的创建命令只展示有关挂载,适用于独立验证容器。镜像是占位值,应换成已经批准、具有正确默认启动命令的镜像;正式服务还要保留原来的用户、环境、网络、其他卷和启动参数:

docker run --name media-reader-check \
  --mount type=bind,source=/media,target=/media,bind-propagation=rslave \
  your-approved-image:version

这条示例没有添加只读限制,应按应用真实需要保留或设置相应读写策略。传播方向和文件读写权限是两项设置,不能把 rslave 解释成“容器只能读”。若要求所有子挂载也严格只读,还需核对递归只读能力及内核条件,不能只看父目录的 ro 字样。

只要求宿主机新挂载出现在容器中时,没有必要改为双向 rshared。也不要把这项调整与 --privileged、允许容器自行解锁磁盘或增加所有设备访问混在一起。

已有容器的挂载参数需要按部署流程应用到新容器。操作前保存旧配置和仍需保留的容器可写层数据,安排服务中断窗口;单纯重启应用进程不会重建这项绑定。

验证后挂载的可见性,再恢复业务读取

先验证配置里的传播值,再在隔离验证环境中检查宿主机正常新增子挂载后,容器是否能看到相同文件系统中的预期标识文件。使用真实可识别的测试文件核对内容,而不是只看同名目录存在。

同时确认不相关的宿主机目录没有意外暴露,业务程序确实读取预期路径。既有挂载点的可见性通过,不代表“容器创建之后新增挂载”的场景也已通过;验证顺序必须对应故障触发顺序。

回退时恢复原来的传播参数和部署配置,再重建目标容器。宿主机若另行调整过挂载传播属性,需要按此前记录单独恢复;不要为了回退容器配置卸载仍被业务使用的设备。停止容器也不会自动撤销宿主机上的设备挂载或此前已写入的数据。