containerd task死锁导致docker stop无响应时,需先终止shim进程,再手动清理task元数据目录并重启containerd;预防应升级containerd、配置cgroup及禁用新权限。

当 docker stop 长时间无响应,且容器状态显示为 removing 或卡在 exited 但 PID 仍存在,大概率是 containerd 的 task 服务发生死锁——这属于底层运行时级阻塞,常规 kill 或 restart docker 无效。
确认是否为 containerd task 死锁
先验证问题根源,避免误操作:
- 执行
sudo crictl ps -a(若安装 cri-tools)或sudo ctr -n moby containers list,查看容器是否在 containerd 中处于STOPPED但未被清理 - 检查 containerd task 状态:
sudo ctr -n moby tasks ls,若目标容器 ID 对应的 task 显示STATUS=RUNNING或长时间卡在STOPPING,即为 task 层死锁 - 观察 containerd 日志是否有重复报错:
sudo journalctl -u containerd -n 100 --no-pager | grep -i "task\|shim\|exit",常见线索包括failed to delete task、wait pid failed、shim disconnected
终止卡住的 shim 进程(最常用有效手段)
containerd 为每个容器启动一个 containerd-shim 进程代理生命周期管理。shim 挂起会导致 task 无法退出:
使用 Python 脚本下载 Docker 镜像并打包为 tar 文件。用户说“下载镜像”“拉取镜像”“pull xxx”“帮我下载 nginx 镜像”等时触发。支持 SOCKS5 代理直连(推荐)和国内镜像站加速两种模式。
- 定位 shim 进程:
ps aux | grep 'containerd-shim.*[container_id]'(用容器 ID 前几位匹配) - 强制终止 shim:
sudo kill -9 $(pgrep -f "containerd-shim.*[container_id]") - 再次执行
docker stop [container_id],通常可立即返回;如仍卡住,说明 shim 已退出但 task 元数据残留
手动清理 containerd 中残留 task 和容器对象
shim 终止后,若 containerd 内部状态未同步,需人工干预:
- 停止 containerd:
sudo systemctl stop containerd - 进入 containerd 的元数据目录:
cd /var/lib/containerd/io.containerd.runtime.v2.task/moby/ - 查找并删除对应容器 ID 的子目录(该目录名即容器 ID):
sudo rm -rf [container_id]* - 重启 containerd:
sudo systemctl start containerd - 此时再运行
docker ps -a,该容器应已消失;若仍显示,可补删/var/lib/docker/containers/[container_id]/目录(仅限容器已确定不可恢复)
预防与长期加固措施
task 死锁多由内核兼容性、cgroup v2 配置异常或 shim 与内核信号处理缺陷引发:
- 升级 containerd 至 v1.7.13+ 或 v1.8.6+(修复多个 shim 信号转发死锁 CVE)
- 检查 cgroup 版本:
stat -fc %T /sys/fs/cgroup,若为cgroup2fs,确保内核 ≥ 5.8 且/proc/sys/user/max_user_namespaces≥ 1024 - 在
/etc/containerd/config.toml中显式配置:[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] SystemdCgroup = true
(避免 cgroup 路径竞争) - 禁用不必要功能:在 daemon.json 中添加
"no-new-privileges": true,减少 shim 权限膨胀风险

















