Docker 绑定挂载目录中的文件未更新
Posted
技术标签:
【中文标题】Docker 绑定挂载目录中的文件未更新【英文标题】:Files within Docker bind mount directory not updating 【发布时间】:2019-05-02 01:04:30 【问题描述】:我正在使用 docker bind mount 来映射 Ubuntu 生成的主机 /dev/serial/
文件夹(其中包含识别符号链接到串行设备,例如 /dev/ttyUSB0
)。我正在使用的完整 docker 容器运行命令是
docker run -d --restart always --privileged=true -v /dev/serial:/dev/serial DOCKER_IMAGE_NAME
这在第一次运行时工作正常,但是如果串行设备断开连接并重新连接,则重新创建符号链接。此更改不会传播到 docker 容器中,而是 docker 容器会找到一个空的 /dev/serial
文件夹。我也测试了在主机上和该目录的 docker 容器中手动创建文件,奇怪的是,在这两种情况下,另一种情况下的更改都没有更新。
音量显示为
"Type": "bind",
"Source": "/dev/serial",
"Destination": "/dev/serial",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
编辑:Ubuntu 在/dev/serial
文件夹下的两个目录by-path
和by-id
中创建符号链接。
【问题讨论】:
在我的情况下,挂载显示完美,即源和目标是正确的,但文件夹内容没有得到更新。重新启动 Docker 最终会暴露文件,即再次建立绑定挂载连接。注意:我正在将 Windows 位置安装到 linux 容器 【参考方案1】:绑定挂载基于 inode,当文件被删除并重新创建时,绑定挂载会被破坏。在容器重新启动之前,这些更改不会传播到绑定挂载,因此它会选择新的 inode。
这种情况的解决方案(文件被删除并重新创建)是挂载父目录,因此在您的情况下,您可以使用-v /dev:/dev
进行挂载。当然,这会将 /dev 暴露给容器,因此请小心处理。
【讨论】:
感谢您的回复。我没有意识到,当设备被拔出时,Ubuntu 不仅会删除/dev/serial
下的子目录中的符号链接,还会删除 /dev/serial
目录本身。安装 /dev
效果很好。
即使我挂载了文件所在的目录而不是文件本身,如果在容器运行时删除并重新创建文件,文件仍然不会从容器接收新数据。它可能仍然是一个“inode”问题,但提出的解决方案不起作用。【参考方案2】:
以前版本的 Docker 存在此问题。 Sebastian Van 已经清楚地解释了同样的原因
这看起来像一个竞争条件;这里的问题是,当使用 -v : 选项时,如果路径不存在,docker 将自动创建。此功能在某些时候被标记为弃用(正是因为这些问题),但它被认为是太多的破坏性更改(请参阅 moby/moby#21666,以及与该问题相关的问题)。
Docker for Windows(运行 Linux 容器时)在 VM 中运行 docker 守护程序。从本地 (Windows) 计算机共享的文件/目录使用共享挂载与 VM 共享,我怀疑在容器启动时挂载尚未存在。
因此,在 VM 中找不到 %USERPROFILE%/docker_shared 目录,因此守护程序会创建该路径(作为空目录)。稍后,当共享挂载(来自 Windows 主机)存在时,它会挂载在 VM 内 %USERPROFILE% 目录的“顶部”,但此时容器已经启动。
重新启动(docker stop,docker start)解决了这种情况,因为此时共享挂载可用,并且容器将挂载正确的路径。
关注主题:https://github.com/docker/for-win/issues/1192 以获得更好的理解。该问题已在 Docker 版本 2.0.4.0(边缘通道)和更高版本的稳定版本中得到解决。
【讨论】:
以上是关于Docker 绑定挂载目录中的文件未更新的主要内容,如果未能解决你的问题,请参考以下文章