Docker容器中运行着多个进程,它们的PID在容器名称空间中是隔离的,是否有办法找出Docker主机上的PID是什么?
例如,有一个Apache Web服务器在Docker容器中运行(我使用Docker Hub中的Apache + PHP映像),而Apache在启动时会在该容器内创建更多工作进程。这些工作进程实际上正在处理传入的请求。要查看这些进程,我pstree
在docker容器中运行:
# pstree -p 1
apache2(1)-+-apache2(8)
|-apache2(9)
|-apache2(10)
|-apache2(11)
|-apache2(12)
`-apache2(20)
父Apache进程在容器进程名称空间内的PID 1上运行。但是,从主机的角度来看,也可以访问它,但是其在主机上的PID是不同的,可以通过运行以下docker compose
命令来确定:
$ docker inspect --format '{{.State.Pid}}' container
17985
从中我们可以看到容器过程名称空间中的PID 1映射到主机上的PID 17985。因此,我可以pstree
在主机上运行,以列出Apache进程的子进程:
$ pstree -p 17985
apache2(17985)─┬─apache2(18010)
├─apache2(18011)
├─apache2(18012)
├─apache2(18013)
├─apache2(18014)
└─apache2(18164)
据此,我假设容器中的PID 1映射到主机上的PID 17985的方式相同,它还映射:
(这允许我使用仅在主机上可用,而在容器中不可用的工具(例如strace)从docker容器调试进程)
问题是我不知道假设pstree在容器和主机中以相同顺序列出进程是多么安全。
如果有人可以提出一种更可靠的方法来检测运行在Docker容器内的特定进程的主机上的PID的话,那就太好了。
你可以查看/proc/<pid>/status
文件以确定名称空间PID和全局PID之间的映射。例如,如果在Docker容器中我启动了多个sleep 900
过程,如下所示:
# docker run --rm -it alpine sh
/ # sleep 900 &
/ # sleep 900 &
/ # sleep 900 &
我可以看到它们在容器中运行:
/ # ps -fe
PID USER TIME COMMAND
1 root 0:00 sh
7 root 0:00 sleep 900
8 root 0:00 sleep 900
9 root 0:00 sleep 900
10 root 0:00 ps -fe
我可以在主机上查看这些内容:
# ps -fe | grep sleep
root 10394 10366 0 09:11 pts/10 00:00:00 sleep 900
root 10397 10366 0 09:12 pts/10 00:00:00 sleep 900
root 10398 10366 0 09:12 pts/10 00:00:00 sleep 900
对于其中任何一个,我都可以查看该status
文件以查看名称空间pid:
# grep -i pid /proc/10394/status
Pid: 10394
PPid: 10366
TracerPid: 0
NSpid: 10394 7
看这NSpid
行,我可以看到在PID名称空间中,该进程具有pid7。确实,如果我10394
在主机上终止了该进程:
# kill 10394
然后在容器中,我看到PID 7不再运行:
/ # ps -fe
PID USER TIME COMMAND
1 root 0:00 sh
8 root 0:00 sleep 900
9 root 0:00 sleep 900
11 root 0:00 ps -fe
看起来它解决了我的问题,按照以下建议,我可以使用这种单线检索PID的完整映射:
for i in $(ps -ef | grep $(docker inspect --format '{{.State.Pid}}' php-sandbox) | awk '{print $2}') ; do grep NSpid: /proc/$i/status ; done
请注意,NSpid仅从Linux 4.1开始可用。因此这可能不适用于较旧的计算机。或者,您可以通过docker执行grep -l pid / proc / * / sched查找容器内pid。
这似乎在Mac上不起作用。
docker top
当我运行时,命令给定的pid不存在ps
。其次,在Mac上没有/ proc。这是因为在Mac上,您正在Linux VM上运行Docker。如果要登录Linux VM,您将看到此处描述的行为。
gr8问题与解答。这对我有用-
for i in $(ps -ef | grep `docker inspect --format '{{.State.Pid}}' containerID` | awk '{print $2}') ; do grep NSpid: /proc/$i/status ; done
。谁能提出为什么原来没用的建议。