Docker卷与设备映射机制及特权模式下重新挂载问题
我来帮你理清这几个Docker卷挂载的细节问题,都是实际使用中容易碰到的底层逻辑困惑:
1. Docker挂载卷时,如何与/dev/sda1设备建立映射?
首先要明确:你在Mac上使用Docker时,Docker实际运行在一个后台的Linux虚拟机(VM)里,容器里看到的/dev/sda1其实是这个Linux VM的根文件系统设备。
Docker的命名卷(named volume)默认使用local驱动,实际存储路径是VM里的/var/lib/docker/volumes/<volume-name>/_data,而这个路径本身就位于VM的/dev/sda1设备上。
当你执行docker create命令挂载卷时,Docker并不是直接把/dev/sda1块设备挂载到容器里,而是通过**绑定挂载(bind mount)**的方式,把VM中/var/lib/docker/volumes/volume1/_data这个目录挂载到容器的/var/vcap/store路径,同理volume2对应/var/vcap/store2。容器里的mount命令显示/dev/sda1作为挂载源,是因为绑定挂载会显示底层存储设备的信息,而非直接挂载块设备本身。
2. 同一设备对应不同文件系统是如何实现的?
这其实是个误解——并不是同一设备对应不同文件系统,而是所有这些挂载点都是不同的绑定挂载,它们共享同一个底层存储设备(VM的/dev/sda1),但挂载的是该设备上的不同路径:
/var/vcap/store和/var/vcap/store2挂载的是VM里的两个不同卷数据目录/etc/resolv.conf、/etc/hostname、/etc/hosts是Docker自动挂载的临时配置文件,这些文件本身也存储在VM的/dev/sda1上
容器里的mount输出会显示底层设备(/dev/sda1)和文件系统类型(ext4,也就是VM根文件系统的类型),但每个挂载点对应的实际内容是完全独立的,只是共享了同一个存储设备而已,并不是把同一个块设备重复挂载到多个目录。
3. 在特权模式下,应使用何种mount命令重新挂载已卸载的文件系统?
你直接执行mount /dev/sda1 /var/vcap/store会看到陌生内容,是因为这会把整个Linux VM的根文件系统挂载到容器目录下,那些cni、containerd目录都是VM根目录里的内容,显然不是你要的卷数据。
正确的做法是通过绑定挂载指向卷在VM里的实际数据目录,步骤如下:
- 先把VM的根文件系统挂载到容器内的一个临时目录:
mount /dev/sda1 /mnt/hostroot - 再将对应的卷数据目录绑定挂载到目标路径:
同理,挂载mount --bind /mnt/hostroot/var/lib/docker/volumes/volume1/_data /var/vcap/storevolume2的命令是:mount --bind /mnt/hostroot/var/lib/docker/volumes/volume2/_data /var/vcap/store2
另外,更推荐的方式是尽量避免在容器内手动挂载卷,如果需要重新挂载,最好通过重启容器并指定Docker的-v参数来实现,这样更符合Docker的设计逻辑。
内容的提问来源于stack exchange,提问作者Salvatore D'angelo

