容器为什么删不掉
docker rm 卡住或提示 Removal In Progress、device or resource busy,本质是 daemon 拆不掉容器的最后一层。常见原因分三类:容器还活着但进程无法被正常终止(处于不可中断状态),挂载点被占用(宿主目录还被别的进程引用,或远端存储无响应),以及 containerd 或 dockerd 的状态残留。前两类必须到宿主侧排查,第三类通常重启 docker 就能清掉。
基本信息
| 第一步 | docker rm -f <容器>,完整保留报错文本 |
|---|---|
| 看残留状态 | docker ps -a --filter status=removing --filter status=dead |
| 查挂载占用 | grep <容器 ID 前缀> /proc/mounts |
| 查残留进程 | ps -ef 过滤 containerd-shim 与 runc |
| 兜底手段 | 重启 docker,让 daemon 重建运行时状态 |
| 真实原因 | journalctl -u docker 看 daemon 侧日志 |
| 适用范围 | Linux 宿主;含 bind 挂载与远端存储的场景更常见 |
典型使用场景
- 容器已经停止,docker rm 却长时间没有响应
- 删除后 docker ps -a 里一直显示正在删除的状态
- 挂了宿主目录或远端存储的容器删不掉,报 device or resource busy
- 批量清理测试环境时被一两个顽固容器卡住整个脚本
- 磁盘告警要紧急腾空间,却删不掉占着存储层的容器
排查与处理顺序
排查与处理顺序
docker rm -f web # 先强删,完整记录报错文本
docker ps -a --filter status=removing --filter status=dead # 看残留状态
grep -i <容器ID前缀> /proc/mounts | head -5 # 找占用该容器挂载点的条目
ps -ef | grep -E 'containerd-shim|runc' | grep -v grep # 看残留的运行时进程
journalctl -u docker --since '10 min ago' | tail -30 # daemon 侧的真实原因
sudo systemctl restart docker # 兜底:让 daemon 重建状态后重试删除卡住原因对照
| 原因 | 判断依据 | 处理方向 |
|---|---|---|
| 运行时状态残留 | 报错含 Removal In Progress,ps -a 显示正在删除 | 重启 docker 后重试删除 |
| 挂载点被占用 | 报 device or resource busy,/proc/mounts 仍有该路径 | 找到占用进程结束它,再重试删除 |
| 远端存储无响应 | 挂载点指向 NFS 或云盘,连 umount 也卡住 | 先恢复存储侧可用性,再处理容器 |
| 进程处于不可中断状态 | ps 显示该进程状态为 D | 查内核与存储,等待 IO 恢复,重启未必有用 |
| 卷仍被使用 | 报错提到 volume 或卷名 | 确认使用方,再决定删卷还是保留 |
docker rm -f 发送的是 SIGKILL,对处于不可中断状态的进程无效,硬等不会成功。先确认进程卡在哪个设备或存储上,再决定是恢复存储还是重启服务。
处理完用 docker ps -a 与 daemon 的容器目录双向核对,确认条目真的消失。daemon 的元数据目录不要手工删除,容易让状态与实际不一致,清理交给 daemon 自己完成。
手动 umount 之前必须确认目标路径确实属于这个容器。宿主的共享挂载点或远端存储一旦被误卸载,影响面可能远超这一个容器,恢复还要重新挂载。