虽然Docker是经过namespace隔离技术实现容器间进程的隔离,但在运行Docker的主机中,Docker容器内的进程与主机内运行的进程是在同一个namespace(假设叫A)的。虽然在Docker容器内应用进程的父进程都是pid为1的那个进程(这些进程都是单独的namespace,这个namespace与前面提到的namespace不是同一个,此处假设为B),但在namespace A中Docker内容器实际的父进程都是Docker daemon,因为父进程具备对子进程管理的能力,而子进程不能影响到父进程也不能影响到其余namespace的进程,因此能实现进程隔离。git
因为Docker容器内的进程与主机内运行的进程是在同一个namespace,因此在主机中使用ps -ef命令能够查找出当前系统中运行的全部进程,这些进程包含了完整的与Docker有关的全部进程,在这个namespace中,这些进程的父进程(无论是父进程仍是父父进程)都包含Docker daemon,所以能够从Docker容器某进程的pid开始,一直找到主机的init进程。github
有时咱们须要根据docker容器进程的pid找到这个容器的容器id,这时经过Linux系统自带的基础命令是没法完成这一操做的。但要想经过pid获取容器id,办法仍是有的。其中有两种可行的办法。docker
第一种根据:docker inspect <CONTAINER ID>能够获取容器的pid,经过docker ps能够获取容器的容器id,所以能够将这两个命令结合在一块儿,利用下面的命令行就能够解决:bash
docker inspect -f '``.`State`.`Pid` ``.`Id`' $(docker ps -a -q) | grep <pid>
可是第一种有一个缺陷,那就是若是这个进程刚好是容器内进程的子进程,那么这个进程就不会再在主机的namespace中出现,由于只有容器的pid为1的进程才会在主机的namespace中出现。所以就必须使用第二种方法。ide
第二种:在Docker Version 1.11后,增长了“containerd”,根据这个特性的实现方式能够直接经过此进程的父进程的cmdline找到它的容器id。这个方法的缺点就是不适用于Docker Version 1.11以前的版本。函数
根据这两种特性,编写了一个Python脚本,用于发现:spa
1.查找pid所对应的容器id,并打印容器的详细信息命令行
2.获取此进程的进程树和含有命令行的进程树blog
脚本中还隐藏了一种根据进程推导出进程所占用端口号的函数。这个功能在此脚本中用处不大,但在别处有用处。进程
因为脚本内容比较长,所以能够从Gitub上获取此脚本:https://github.com/DingGuodong/LinuxBashShellScriptForOps/tree/master/projects/LinuxSystemOps/SoftwareManagement/docker。
运行效果图(若是看不清,请使用新标签页打开图片查看原图)以下:
Docker Server Version < 1.11
一个第一种方法失败的例子。
此时,就有必要借助第二种方法实现(若是看不清,请使用新标签页打开图片查看原图)。
题外话:
关于init进程,“init进程是全部Linux进程的父进程”,这句话实际上是错的!也许应该说init进程是全部Linux用户空间进程的父进程,pid 2 [kthreadd]是Linux系统内核空间进程的父进程。除了2之外,三、四、5等也是特殊进程pid,它们的父进程都不是init。除此以外,0也是一个特殊的进程,用于进程调度。
tag: 经过pid得到容器id,容器namespace,如何查找容器id
--end--