如何在Docker容器内获取主机正确的磁盘使用信息
核心原因
--privileged 参数仅会给容器开放全部Linux capability、透传所有主机块设备、关闭默认的seccomp/AppArmor安全限制,不会默认共享主机的挂载命名空间。df 命令的工作逻辑是读取当前命名空间下的 /proc/mounts 挂载表,再通过 statfs 系统调用读取对应挂载点的容量数据。你的容器当前使用独立挂载命名空间,里面只有容器自身的overlay挂载、tmpfs、shm以及几个默认bind的配置文件,自然看不到主机上其他磁盘分区的挂载记录。
另外你容器内lsblk看不到加密LVM层,是因为Alpine镜像默认不带lvm2、cryptsetup工具,无法识别device mapper的加密、逻辑卷映射关系,不是权限不够。
方案1:让容器内
df输出和主机完全一致 如果不需要保留容器和主机的挂载隔离,启动容器时追加以下参数即可:
docker run --privileged --pid=host -v /proc/mounts:/proc/mounts:ro --propagation=shared 你的其他启动参数 镜像名
参数说明:
--pid=host:共享主机PID命名空间,保证容器能读取主机完整的/proc目录下的系统信息-v /proc/mounts:/proc/mounts:ro:直接把主机的挂载表只读挂载到容器内,替换容器自身的挂载表--propagation=shared:开启挂载事件共享,主机后续新插入磁盘、新挂载分区的事件会同步到容器内
启动后在容器内安装必要的识别工具:
apk add lsblk lvm2 cryptsetup
此时执行lsblk、df的输出会和主机完全一致。
注意:这个方案会大幅降低容器隔离性,容器内的挂载操作会直接影响主机,仅建议测试环境使用。
方案2:保留隔离性,在容器内获取主机磁盘数据
如果不想破坏容器隔离,不需要让原生df直接输出主机结果,可以用以下方式获取数据:
- 启动容器时把主机根目录只读挂载到容器内,追加启动参数:
-v /:/host:ro,rshared - 容器内安装依赖工具:
apk add lsblk lvm2 cryptsetup coreutils - 数据获取方式:
- 块设备硬件总容量:直接执行
lsblk即可读取,不需要额外配置,块设备已经通过--privileged透传 - 主机各分区使用率、挂载点:读取
/host/proc/mounts拿到主机全量挂载点列表,对每个挂载点路径加/host前缀后,执行df -h /host/对应挂载路径就能拿到准确的容量、使用率数据,比如要读主机sda1分区(挂载在/media/mauz/ESD-ISO)的使用率,执行df -h /host/media/mauz/ESD-ISO即可 - LVM、加密分区结构:安装完lvm2和cryptsetup后,执行
vgscan --mknodes就能识别到LVM逻辑卷,需要访问加密分区内容时再执行cryptsetup命令打开映射即可,识别后lsblk会输出和主机一致的完整磁盘分层结构
- 块设备硬件总容量:直接执行
补充:你当前容器内看到的/dev/mapper/vgubuntu-root容量数据和主机根分区是一致的,数值微小差异是容器启动后产生的少量写入导致,属于正常情况。
内容的提问来源于stack exchange,提问作者MauriceNino
相关产品推荐
相关产品推荐

