版权声明:本文为(haibing.org)原创文章,转载请附上本文链接。
本文永久链接:http://haibing.org/757

一、问题描述
CentOS7.2中,在Dockerfile文件或者在容器里面执行rm -rf会不成功,提示Directory not empty

二、原因分析
执行docker info查看docker信息
# docker info

Client:
Debug Mode: false

Server:
Containers: 1
Running: 1
Paused: 0
Stopped: 0
Images: 11
Server Version: 19.03.2
Storage Driver: overlay2
Backing Filesystem: xfs
Supports d_type: false
Native Overlay Diff: false
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
Volume: local
转载本站文章请注明出处:haibing.org
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
Swarm: inactive
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 894b81a4b802e4eb2a91d1ce216b8817763c29fb
runc version: 425e105d5a03fabd737a126ad93d62a9eeede87f
init version: fec3683
Security Options:
seccomp
Profile: default
Kernel Version: 3.10.0-327.el7.x86_64
Operating System: CentOS Linux 7 (Core)
OSType: linux
转载本站文章请注明出处:haibing.org
Architecture: x86_64
CPUs: 4
Total Memory: 7.64GiB
Name: logserver
ID: 32TU:J6RR:7U23:ZLCB:NG7N:JUU7:7PS2:SOSY:WBCL:6COG:OEUS:UN6I
Docker Root Dir: /var/lib/docker
Debug Mode: false
Registry: https://index.docker.io/v1/
Labels:
Experimental: false
Insecure Registries:
转载本站文章请注明出处:haibing.org
127.0.0.0/8
Live Restore Enabled: false

WARNING: bridge-nf-call-iptables is disabled
WARNING: bridge-nf-call-ip6tables is disabled
WARNING: overlay2: the backing xfs filesystem is formatted without d_type support, which leads to incorrect behavior.
Reformat the filesystem with ftype=1 to enable d_type support.
Running without d_type support will not be supported in future releases.

注意这几个信息:
Storage Driver: overlay2
Backing Filesystem: xfs
Docker Root Dir: /var/lib/docker

警告信息说这Backing Filesystem是没有启用d_type支持的xfs文件系统,如果要支持的话,需要设置 ftype=1 重新格式化系统,启用d_type。

查询当前/var/lib/docker所在分区的ftype信息
# xfs_info /var/lib/docker|grep ftype
naming =version 2 bsize=4096 ascii-ci=0 ftype=0
转载本站文章请注明出处:haibing.org

通过上面的信息可以看出,这是因为Storage Driver使用的overlay2,而docker默认保存文件的目录/var/lib/docker所在分区格式是使用了没有开启d_type的xfs格式,才造成使用rm -rf删除文件出错。

三、解决办法
网上有人说可以通过修改storage-driver为devicemapper来解决这个问题,这种方法是错误的。
修改后会有个提示,说devicemapper不推荐使用的,而且在未来版本要被移除的。

WARNING: the devicemapper storage-driver is deprecated, and will be removed in a future release.
WARNING: devicemapper: usage of loopback devices is strongly discouraged for production use.
Use `--storage-opt dm.thinpooldev` to specify a custom block storage device.
转载本站文章请注明出处:haibing.org

而且如果从overlay2转到devicemapper后,并不能识别以前的容器信息。

修复这个问题,最好的办法就是把docker文件存在一个启用了d_type的xfs分区中。

这里提供两种方案:
1、不改变默认存放地址,把当前分区转成启用了d_type的xfs分区
2、改变默认存放地址,指向新的启用了d_type的xfs分区

1 、不改变默认存放地址,把当前分区转成启用了d_type的xfs分区
这里也要分两种情况:
a、/var/lib/docker原先已经是一个单独分区:只需要先把里面的东西移出来,重新使用xfs格式化一下(设置 ftype=1),再把东西移回去就可以了。
b、/var/lib/docker跟其它目录共用分区:那需要新增一个分区,格式化(设置 ftype=1),临时随便挂载到一个目录上,把原先/var/lib/docker里面的东西全部移动这个临时目录中,东西全部移完后,再重新挂载这个分区到/var/lib/docker目录上即可。
转载本站文章请注明出处:haibing.org

先停止正在使用的容器
# docker stop $(docker ps -a | awk ‘{ print $1}’ | tail -n +2)
 
停止docker服务
# systemctl stop docker
 
确认一下(没有任何输出说明停止成功了)
# lsof /var/lib/docker
 
a、如果/var/lib/docker原先已经是一个单独分区:
# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sdc 16G 968M 16G 6% /var/lib/docker
 
把/var/lib/docker里面的东西先移出去,随便先存放在一个目录中
# mv /var/lib/docker/* /media/
 
使用mkfs带上ftype=1重新格式化/var/lib/docker所挂载的单独分区
# umount /var/lib/docker
# mkfs -t xfs -n ftype=1 /dev/sdc
 
然后再把东西移回去就可以了
# mount /dev/sdc /var/lib/docker
# mv /media/* /var/lib/docker/
转载本站文章请注明出处:haibing.org

b、如果/var/lib/docker是跟其它目录共用分区:
增加一个大小适当的磁盘(分区可以使用LVM),格式化时注意添加上 ftype=1的参数
# mkfs -t xfs -n ftype=1 /dev/sdc
 
临时随便创建一个目录,把新磁盘挂载上去
# mount /dev/sdc /docker
  
把/var/lib/docker里面的东西全部移到新挂载的临时目录上
#mv /var/lib/docker/* /docker/
 
# ls /docker
builder buildkit containers image network overlay2 plugins runtimes swarm tmp trust volumes
转载本站文章请注明出处:haibing.org

然后umount新分区,把这个磁盘挂载到/var/lib/docker上
# umount /docker
# mount /dev/sdc /var/lib/docker
 
把挂载信息写进fstab中
# echo “/dev/sdc /var/lib/docker xfs defaults 0 0” >> /etc/fstab
 
# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sdc 16G 968M 16G 6% /var/lib/docker
 
重新启动docker服务,测试一下是不是可以在容器中使用rm -rf删除东西了
转载本站文章请注明出处:haibing.org

2、改变默认存放地址,指向新的启用了d_type的xfs分区
新增一个分区,格式化时设置 ftype=1,挂载到一个新目录上,把原先/var/lib/docker里面的东西全部移动这个新目录中,东西全部移完后,修改docker的配置文件,把原先默认的/var/lib/docker地址指向新的目录上。
 
先停止正在使用的容器
# docker stop $(docker ps -a | awk ‘{ print $1}’ | tail -n +2)
 
停止docker服务
# systemctl stop docker
 
确认一下(没有任何输出说明停止成功了)
# lsof /var/lib/docker
 
增加一个大小适当的磁盘(分区可以使用LVM),格式化时注意添加上 ftype=1的参数
# mkfs -t xfs -n ftype=1 /dev/sdc
 
创建一个目录/docker,把新分区挂载上去
# mount /dev/sdc /docker
  
把/var/lib/docker里面的东西全部移到新挂载的目录/docker上
#mv /var/lib/docker/* /docker/
 
# ls /docker
builder buildkit containers image network overlay2 plugins runtimes swarm tmp trust volumes
 
把挂载信息写进fstab中
# echo “/dev/sdc /docker xfs defaults 0 0” >> /etc/fstab
 
# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sdc 16G 968M 16G 6% /docker
 
先不要启动docker服务,修改docker配置,指向新的保存地址/docker。
 
这个修改docker存储默认路径的方法也有很多的。
一种修改daemon.json:
# vim /etc/docker/daemon.json
 
{
“graph”: “/docker/”
}
  
一种是修改服务文件:
vim /usr/lib/systemd/system/docker.service
在里面的EXECStart的后面增加后如下:
ExecStart=/usr/bin/dockerd –graph /docker

修改完配置后,重新刷新启动服务
systecmtl daemon-reload
systemctl start docker
转载本站文章请注明出处:haibing.org

注:
–graph这个参数在v17.05.0版本也不提供使用了(但还可以用),现在提倡采用–data-root
(见https://docs.docker.com/engine/deprecated/)

1 对 “docker中rm: cannot remove ‘/xxx/xxxxx’: Directory not empty”的想法;

评论被关闭。