docker remove container encounter device or resource busy

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,可以看到两个旧容器都被删除了,只剩下新容器,好像有点类似擦除这样的概念。
具体为什么,在源码里面没有找到,不清楚。

你可能感兴趣的:(docker remove container encounter device or resource busy)