docker top 看到的 PID 为什么和容器里 ps 不一样?它怎么知道用户名?容器里没有 ps 怎么办?这篇逐项对比 docker top、docker exec ps 和 /proc 里的 NSpid。
docker top(默认列):
UID PID PPID C STIME TTY TIME CMD
root 53711 53687 0 13:42 ? 00:00:00 sh -c sleep 300 & sleep 301 & wait
root 53725 53711 0 13:42 ? 00:00:00 sleep 300
root 53726 53711 0 13:42 ? 00:00:00 sleep 301
docker exec ps(容器里的视角):
PID PPID COMMAND COMMAND
1 0 sh sh -c sleep 300 & sleep 301 & wait
7 1 sleep sleep 300
8 1 sleep sleep 301
9 0 ps ps -o pid,ppid,comm,args
容器主进程在虚拟机里的 PID = 53711;/proc/53711/status 的 NSpid = NSpid: 53711 1docker top 在虚拟机里对容器 cgroup 里的进程跑 ps,所以 PID 是虚拟机的 PID;容器里的 ps 看到的是容器自己的 PID 命名空间。/proc/<PID>/status 的 NSpid 能把两个编号对上。
docker top -o pid,ppid,user,comm:退出码 0;PID PPID USER COMMAND | 53711 53687 root sh | 53725 53711 root sleep docker top aux:退出码 0;USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND | root 53711 0.0 0.0 1732 1072 ? Ss 13:42 0:00 sh -c sleep 300 & sleep 3 | root 53725 0.0 0.0 1716 880 ? S 13:42 0:00 sleep 300 docker top -eo pid,nlwp,rss,etime,args:退出码 0;PID NLWP RSS ELAPSED COMMAND | 53711 1 1072 00:01 sh -c sleep 300 & sleep 301 & wait | 53725 1 880 00:01 sleep 300
docker top 后面的参数原样交给虚拟机里的 ps,可以自定义列、用 aux 等写法;输出里必须有 PID 列。
容器里 uid 1 的名字(容器的 /etc/passwd):bin / bin 虚拟机里 uid 1 的名字:daemon docker top 显示这个进程的 UID 列:UID PID PPID C STIME TTY TIME CMD | daemon 53878 53853 0 13:42 ? 00:00:00 sl docker top -o user,uid:Error response from daemon: Couldn't find PID field in ps output
用户名是虚拟机的 ps 去解析的,容器里的 /etc/passwd 对它没用:同一个 uid 1,容器里叫 bin,docker top 显示的是虚拟机里的 daemon。
scratch 镜像里 docker exec ps:退出码 127;OCI runtime exec failed: exec failed: unable to start container process: exec: "ps": executable file not found 同一个容器 docker top:UID PID PPID C STIME TTY TIME CMD | root 54092 54068 0 13:42 ? 00:00:00 /app
distroless 或 scratch 镜像里没有 ps,docker exec 无计可施,docker top 仍然可用,是排查这类容器的少数办法之一。僵尸进程在 docker top 里看不到,见 c31。