problem:
driver "devicemapper" failed to remove root filesystem for 1beae7c9e719ac2568820b4e75e6a73c4ffb94611534c22157d4228ecd9877b5: remove /home/ueba-data/docker/devicemapper/mnt/2f73210f6bab99437cda0b1557058c04de8322f24ea40a4909aaf72b2ace107a: device or resource busy
ERROR: Encountered errors while bringing up the project.
docker 更新镜像后,docker stop containerID之后删除旧容器时,会出现设备或资源繁忙的问题。
由于是更新镜像,在销毁container时由于无法卸载挂接镜像的磁盘导致出错。网上也是说找到挂载点
cat /proc/mounts | grep "mapper/docker" | awk '{print $2}'
,然后依次unmount
。(在我这里不行啊)。
我这里面删除旧容器,或是重启docker restart (docker-compose up -d)依然会出现这个问题,但是不影响新容器的运行(咦,很奇怪哦,实验过很多次,真的不影响)
docker源代码(部分):
// This is used to allow removal of mountpoints that may be mounted in other
// namespaces on RHEL based kernels starting from RHEL 7.4.
// Without this setting, removals on these RHEL based kernels may fail with
// "device or resource busy".
// This setting is not available in upstream kernels as it is not configurable,
// but has been in the upstream kernels since 3.15.
func setMayDetachMounts() error {
f, err := os.OpenFile("/proc/sys/fs/may_detach_mounts", os.O_WRONLY, 0)
if err != nil {
if os.IsNotExist(err) {
return nil
}
return errors.Wrap(err, "error opening may_detach_mounts kernel config file")
}
defer f.Close()
_, err = f.WriteString("1")
if os.IsPermission(err) {
// Setting may_detach_mounts does not work in an
// unprivileged container. Ignore the error, but log
// it if we appear not to be in that situation.
if !rsystem.RunningInUserNS() {
logrus.Debugf("Permission denied writing %q to /proc/sys/fs/may_detach_mounts", "1")
}
return nil
}
return err
}
由于更新镜像并没有为其重新指定挂载点,删除旧容器时,会将旧容器的状态标记为Removal In Process
,旧容器的挂载点不会卸载,还会保留link。但是可以忽略这个错误。
我就是讨厌,重启出现这样的错误,怎么办?
使用 docker-compose down 会导致一些容器异常结束,旧容器的状态变为Dead
,执行
docker rm -f $(docker ps -a -q -f status=dead)
docker-compose -f docker-compose.yml up -d
但是还不行,(呜呜,我要哭了)。
那就找到容器挂载的进程,kill掉。
[root@FJYC-YTSAFEAPP ueba]# grep -l 2f73210f6bab99437cda0b1557058c04de8322f24ea40a4909aaf72b2ace107a /proc/*/mountinfo
/proc/32698/mountinfo 无法找到挂载
然后ps -ef找父进程,找到与旧容器运行的应用进程,kill掉,但是不行啊,(哇,呜呜。。。)。
不行,得解决啊,怎么办?我就猜了一下,既然更新镜像后能够新创建容器并可以运行,那我就再更新一个镜像,将第一次创建的新容器删掉,嘿嘿,也不让你删除,报同样的device or resource busy
,不要管,删除第一次更新的镜像,接着再次更新吧,然后重新新建容器。这样旧容器就变成两个了,而且都是Removal In Process
。
重新新建容器后出现的错误:
driver "devicemapper" failed to remove root filesystem for 1a953cd28c8a5159b1767c5c2fdad83e7bac3d6a71a0e35df6661462681accf3: remove /home/ueba-data/docker/devicemapper/mnt/6a46417f3ccb39157bda0c6251039e04de1309e44ea10a0906aaf72b2adc263a: device or resource busy
Restarting asap-integration_1 ... error
Restarting 1beae7c9e719_asap-integration_1 ... error
ERROR: for 1beae7c9e719_asap-integration_1 b'Cannot restart container 1beae7c9e719ac2568820b4e75e6a73c4ffb94611534c22157d4228ecd9877b5: container is marked for removal and cannot be started'
devicemapper/mnt/6a46417f3ccb39157bda0c6251039e04de1309e44ea10a0906aaf72b2adc263a: device or resource busy
好像没什么区别,就是换成了第二个旧容器的挂载标识。
再次找容器挂载的进程:
[root@FJYC-YTSAFEAPP ueba]# grep -l 6a46417f3ccb39157bda0c6251039e04de1309e44ea10a0906aaf72b2adc263a /proc/*/mountinfo
/proc/1072/mountinfo
/proc/1726/mountinfo
/proc/3208/mountinfo
有什么不一样?没有 “无法找到挂载”
的字样,然后kill进程,重新docker-compose up -d
,出现如下的日志:
Recreating 1beae7c9e719_asap-integration_1 ... error
ERROR: for 1beae7c9e719_asap-integration_1 b'no such image: sha256:b9e0155de7585a614b378b4a827b6077eeca9eb2cd79baa4af78a628075e1a21: No such image: sha256:b9e0155de7585a614b378b4a827b6077eeca9eb2cd79baa4af78a628075e1a21'
ERROR: The image for the service you're trying to recreate has been removed. If you continue, volume data could be lost. Consider backing up your data before continuing.
Continue with the new image? [yN]
输入y,启动成功了,docker ps -a,可以看到两个旧容器都被删除了,只剩下新容器,好像有点类似擦除这样的概念。
具体为什么,在源码里面没有找到,不清楚。