现象:
docker exec无法进入容器,docker ps没有响应,strace跟踪docker daemon进程未发现明显异常(基本是水平不够,所以看不出来),但是能知道docker ps之所以没有响应,是和锁有关系,应该是有一个什么操作阻塞所致。
解决过程:
- docker daemon的事情基本和所启动的容器有关系,可以肯定一点的是,重启daemon就能好,但是该daemon下启动着几十个虚拟机,都将会停止,影响面比较大,而且该问题将来必然还会出现;所以,重启daemon是下下策
- 如果能找到有问题的容器,然后杀掉该容器,或者也许能找到问题根源;但是似乎比较难
- 庆幸的是,从日志上基本可以知道开始出现问题的时候刚好是启动某个容器的时候,那么,很有可能是该容器导致的,不妨试一试
- 所有容器的1号进程都一样,子进程都相像,docker destroy、docker ps 、docker inspect都没有响应,如何杀掉指定的容器?
- 办法: grep 所有容器的config.json,根据容器名确定哪个config.json 是有问题的容器的,然后,该config.json 中有该容器1号进程的pid,然后取出而杀之
- 问题解决
其他想到的:
- 一般来讲,每个容器都有一个hostname,默认是容器id的前面一部分,如果能知道这个问题都好办;但是我们的hostname被自定义了,那么,在知道hostname的情况下,找容器1号进程pid非常方便,因为hostname是进程环境变量的一部分(HOSTNAME),所以,可以:
grep -l the_hostname /proc/*/envrion
其中就包含容器1号进程的pid - 如果能在1号进程名上区分开来会更加方便,我们的docker容器的1号进程都是/sbin/init,如果能添加一个进程/sbin/init 不会在意的多余的参数作为标识,便是极好的(一般来讲是可以的),但是测试发现给/sbin/init 添加的参数在ps的时候都是不给显示的(大概这里的init是entrypoint,不是cmd)
- 在创建容器的时候,给容器指定一个具有标识性的环境变量,也将有助于找到进程的pid
- docker top的时候,我们可以看到容器里面的进程信息,但是这里看到的进程id是容器里面的私有pid,每个私有pid都在宿主机上对应一个全局的pid,根据全局的pid也可以通过 “pstree -p 全局的pid ”来查看容器里面的所有进程,然后,还可以做到不进入容器就能strace容器里面的进程的pid
- nsenter和docker的exec都能进入容器里面,但是docker的exec依赖docker daemon进程,如果docker daemon进程无法响应,就不好使了;而nsenter却不依赖docker daemon进程,直接就可以进入容器内部(我没有试过哦)