Docker:有没有任何方法可以列出正在运行的 Docker 容器内部打开的套接字?

111
我想在运行中的Docker容器内执行netstat命令,以查看开放的TCP套接字及其状态。但是,在我的某些Docker容器上,netstat命令不可用。是否有任何方法可以通过某些Docker API获取开放的套接字(以及它们的状态,以及它们连接到的IP地址(如果有)),而无需使用netstat命令?(顺便说一句,我的容器使用docker-proxy - 也就是说,没有直接桥接)
我猜我可以直接查看/proc文件系统,但是那样的话,我可能会将netstat文件复制到容器中并执行它。我想知道Docker是否提供了任何这方面的功能。
7个回答

218

您可以使用nsenter命令在Docker容器的网络命名空间内运行主机上的命令。只需获取Docker容器的PID:

docker inspect -f '{{.State.Pid}}' container_name_or_id

例如,在我的系统上:
$ docker inspect -f '{{.State.Pid}}' c70b53d98466
15652

一旦您获得了PID,请将其用作nsenter的目标(-t)选项的参数。例如,要在容器网络命名空间中运行netstat

$ sudo nsenter -t 15652 -n netstat
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN     

请注意,即使容器没有安装netstat,该操作也可以成功:
$ docker exec -it c70b53d98466 netstat
rpc error: code = 13 desc = invalid header field value "oci runtime error: exec failed: container_linux.go:247: starting container process caused \"exec: \\\"netstat\\\": executable file not found in $PATH\"\n"

(nsenterutil-linux软件包的一部分)


3
这个解决方案是否适用于其他平台,如Windows、Mac等? - Rao
1
在 AWS EKS 节点上,我是 root 用户,但执行 sudo nsenter -t 14207 -n netstat 命令时返回错误信息:nsenter: cannot open /proc/14207/ns/net: No such file or directory。我可以看到该路径确实存在,但似乎无法对其进行任何操作。有人遇到过这种情况吗? - John Humphreys
nsenter => 权限被拒绝 sudo nsenter => bash: sudo: 找不到命令 - Marc
如果你在Linux上运行,看起来你需要安装和配置sudo或找到另一种以root身份运行命令的方法(如果你不在Linux上运行,则此答案不适用)。 - larsks
我在一个 Linux 容器中(nginx 镜像)。我认为它不是以 root 用户身份运行的,也没有安装任何工具,因此几乎无法进行诊断。 - Marc
显示剩余3条评论

47

@larsks的两个命令合并为一行代码 - 无需复制粘贴PID(只需替换container_name_or_id):

sudo nsenter -t $(docker inspect -f '{{.State.Pid}}' container_name_or_id) -n netstat

1
附注:需要添加另一个“sudo”,使命令变为“... $(sudo docker inspect ...”,否则如果不在根shell中运行,则命令将失败。 - ascendants

6
如果您安装了iproute2软件包,您可以使用以下命令:
sudo nsenter -t $(docker inspect -f '{{.State.Pid}}' container_name_or_id) -n ss

或者
sudo nsenter -t $(docker inspect -f '{{.State.Pid}}' container_name_or_id) -n ss -ltu

这将展示TCPUDP


3
如果你想要所有的容器,请尝试这个。
$ for i in `docker ps -q` ; do sudo nsenter -t $(docker inspect -f '{{.State.Pid}}' $i) -n netstat ; done

1

我尝试了其他解决方案,但都没有起作用。我的同事给了我这个解决方案。我觉得我应该在这里提一下,以帮助像我一样的人,并且以后我也可以参考它。

docker exec -it [容器名称] bash

grep -v “rem_address” /proc/net/tcp


我刚试了一下,它输出了 sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode \n 0: 0B00007F:ABD3 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 479599 1 0000000000000000 100 0 0 10 0 - Luke Schoen

0

docker inspect <container_id>

  • 在 "Config" 中查找 "ExposedPorts"

1
这个实际上显示了正在使用的端口,还是只是容器可以侦听的暴露端口列表? - Jeff Wright

-3
服务器:docker容器列表
CONTAINER ID    IMAGE              COMMAND                  CREATED          STATUS           PORTS       NAMES

80acfa804b59    admirito/gsad:10   "docker-entrypoint.s…"   18 minutes ago   Up 10 minutes    80/tcp      gvmcontainers_gsad_1

3
这是错误的。这只会给出Docker镜像声明和明确暴露的端口(在这两种情况下,容器进程是否实际监听都无关紧要...)。 - Martin Rauscher

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接