Docker cp 提示“no space left on device”
代码语言:javascript复制作者:张首富
时间:2021-05-24
前言
此篇文章记录的并不是 磁盘空间不足
。
问题描述
今天在测试一个功能,需要频繁的替换一个 docker 容器内的一个文件,因为还处在测试阶段,所以我就没有频繁的构建 docker 镜像了;在前几次执行docker cp
命令的时候都能正常的操作。突然再次执行 docker cp
命令时提示如下报错:
# docker cp mod_shine.so fsagent:/usr/local/freeswitch/mod/mod_shine.so
Error response from daemon: mount /data:/data/dockerd/overlay2/63a84fe2d10722bf0cc7cc56537f889eb1f84840bb1c3f8ce8e0272bf55903b7/merged/home, flags: 0x5000: no space left on device
不想看下面直接出解决方案
临时解决
更改下面的 centos 默认挂载磁盘的个数
代码语言:javascript复制echo "1000000" > /proc/sys/fs/mount-max
然后就可以继续docker cp
;永久解决还需要看下面的问题分析
解决问题思路
以为是宿主机没有磁盘空间了
代码语言:javascript复制df -Th #查看磁盘空间,发现还有空间
df -i #查看是否 inode 耗尽发现未耗尽
lsof | grep deleted #查看是否有删除的大文件没有释放,发现并没有
然后通过上面的操作时候确定这个问题不是因为磁盘满或者 inode 耗尽造成的问题,这个时候就有点懵圈了。
仔细分析报错
仔细查看刚才的报错信息,发现是 mount
挂载的时候报错没有空间,猜想:
1,centos 挂载磁盘数量有没有限制? 2,如果有应该如何查看当前挂载了多少? 3,系统默认最多能挂载多少呢?
带着这些疑问和上面的报错信息开始 google,然后在 github 上发现了一个给我相识的问题,https://github.com/moby/moby/pull/38993
问题复现
按照 github 上面的操作复现了这个现象
代码语言:javascript复制$ docker run --name mm -d -v /:/rootfs busybox sleep 3d
73b50c2e626ad9378f429b20ba77355cf815bc9f846f19c173a0e62f57224ad3
$ docker exec mm wc -l /proc/self/mountinfo
86 /proc/self/mountinfo
$ docker cp mm:/etc/group /dev/null
$ docker exec mm wc -l /proc/self/mountinfo
185 /proc/self/mountinfo
$ docker cp mm:/etc/group /dev/null
$ docker cp mm:/etc/group /dev/null
$ docker cp mm:/etc/group /dev/null
$ docker cp mm:/etc/group /dev/null
$ docker cp mm:/etc/group /dev/null
$ docker exec mm wc -l /proc/self/mountinfo
6323 /proc/self/mountinfo
$ docker cp mm:/etc/group /dev/null
$ docker cp mm:/etc/group /dev/null
$ docker cp mm:/etc/group /dev/null
Error response from daemon: mount /:/var/lib/docker/overlay2/c9dbd9463b6c972fa712132d3177cfc19c808ed3e0dcd9a208f7ad487ad40a40/merged/rootfs, flags: 0x5000: no space left on device
$ docker exec mm wc -l /proc/self/mountinfo
50675 /proc/self/mountinfo
问题能复现就能找到具体原因。
分析原因
1, 看这个情况就是挂载的数量达到 centos 系统默认值的上限了;默认值上线是多少呢?
代码语言:javascript复制# cat /proc/sys/fs/mount-max
100000
2, 为什么上图显示才有 50675 的时候在挂载都显示挂载满了呢?
我们可以观察下每次复制都是成倍的增长的。所以我们虽然挂载数量还没达到默认值,但是他不足以支撑下次的挂载了,所以报错了。
3,测试挂载别的目录会不会有这个情况?
我 docker 的家目录在/home/docker
目录下,这点需要注意。
$ docker run --name mm -d -v /data:/data busybox sleep 3d #无上述现象发生
$ docker run --name mm -d -v /tmp:/tmp busybox sleep 3d #无上述现象发生
$ docker run --name mm -d -v /home:/home busybox sleep 3d #上述现象发生
通过这样大量的测试,我发现了,只有在 docker 家目录被挂载到docker 里面之后 docker cp
才会有上述情况,会看出问题的 docker 容器 确实如此。
到此问题找到得以解决
总结
这就是 docker 挂载使用不规范造成的隐藏性的 bug,立即制定 docker 使用规范记录发放到研发人员。以免在造成此类问题发生。