Docker和netstat:netstat没有显示Docker容器暴露的端口

61
我将我的容器的Docker端口暴露给主机,类似这样的方式:

我将我的容器的Docker端口暴露给主机,类似这样的方式:

docker run -p 80:80 ...

然后我尝试使用netstat来显示所有监听端口,以便进行调试,例如:

然后我尝试使用netstat来显示所有监听端口,以便进行调试,例如:

netstat -at

奇怪的是,netstat不会显示我的Docker容器的暴露端口,尽管它们正在侦听并响应浏览器。

我该如何使netstat显示这些暴露的端口?


更新: 我在Debian 8 Jessie上运行。这是我做的:

docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS                      PORTS                                      NAMES
9dfa08bab50d        workflows-nginx     "/bin/sh -c '/usr/sbi"   2 hours ago         Up 2 hours                  0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp   workflows-nginx
d0b0c3f90f13        workflows-django    "/bin/sh -c 'python /"   7 hours ago         Up 3 hours                  0.0.0.0:8000->8000/tcp                     workflows-django
99a857c92533        workflows-db        "/docker-entrypoint.s"   7 hours ago         Up 3 hours                  5432/tcp                                   workflows-db

这里Docker报告容器端口被转发到主机。此外,如果我停止workflows-nginx容器,它将不再通过http(端口80)回答浏览器。如果我重新启动它,则会再次响应。

以下是sudo netstat -at | less的输出:

Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 *:ssh                   *:*                     LISTEN     
tcp        0      0 localhost:ipp           *:*                     LISTEN     
tcp        0      0 *:15672                 *:*                     LISTEN     
tcp        0      0 *:postgresql            *:*                     LISTEN     
tcp        0      0 localhost:smtp          *:*                     LISTEN     
tcp        0      0 *:25672                 *:*                     LISTEN     
tcp        0      0 *:48142                 *:*                     LISTEN     
tcp        0      0 *:sunrpc                *:*                     LISTEN     
tcp        0      0 *:epmd                  *:*                     LISTEN     
tcp        0      0 bob-acer:34866          104.16.33.249:http      ESTABLISHED
tcp        0      0 bob-acer:42380          stackoverflow.com:https ESTABLISHED
tcp        0      0 bob-acer:42543          stackoverflow.com:https ESTABLISHED
tcp        0      0 bob-acer:42525          stackoverflow.com:https ESTABLISHED
tcp        0      0 bob-acer:44076          stackoverflow.com:https ESTABLISHED
tcp        0      0 bob-acer:42944          stackoverflow.com:https ESTABLISHED
tcp        0      0 localhost:epmd          localhost:50831         ESTABLISHED
tcp        0      0 bob-acer:42655          stackoverflow.com:https ESTABLISHED
tcp        0      0 bob-acer:42384          stackoverflow.com:https ESTABLISHED
tcp        0      0 bob-acer:44626          stackoverflow.com:https ESTABLISHED
tcp        0      0 bob-acer:42390          stackoverflow.com:https ESTABLISHED
tcp        0      0 localhost:50831         localhost:epmd          ESTABLISHED
tcp        0      0 bob-acer:48301          c2.52.c0ad.ip4.st:https ESTABLISHED
tcp        0      0 bob-acer:42151          stackoverflow.com:https ESTABLISHED
tcp        0      0 bob-acer:42205          stackoverflow.com:https ESTABLISHED
tcp        0      0 bob-acer:42539          stackoverflow.com:https ESTABLISHED
tcp        0      0 bob-acer:44737          stackoverflow.com:https ESTABLISHED
tcp        0      0 bob-acer:39648          77.94.164.251:https     ESTABLISHED
tcp6       0      0 [::]:ssh                [::]:*                  LISTEN     
tcp6       0      0 localhost:ipp           [::]:*                  LISTEN     
tcp6       0      0 [::]:postgresql         [::]:*                  LISTEN     
tcp6       0      0 localhost:smtp          [::]:*                  LISTEN     
tcp6       0      0 [::]:44794              [::]:*                  LISTEN     
tcp6       0      0 [::]:8000               [::]:*                  LISTEN     
tcp6       0      0 [::]:amqp               [::]:*                  LISTEN     
tcp6       0      0 [::]:sunrpc             [::]:*                  LISTEN     
tcp6       1      0 localhost:58497         localhost:ipp           CLOSE_WAIT

你可以看到,报告中没有80端口或443端口。某种原因导致 workflows-django 的8000端口在IPv6接口上开放。此外,我忘了在主机上禁用postgres,但它们仍然不与postgres容器 workflows-db 冲突。

所有东西都在我的本地笔记本电脑上运行,所以我想主机不会有任何混淆。

我的docker版本是:

docker --version
Docker version 1.10.3, build 20f81dd

回答:这与Docker的EXPOSE参数有关。如果你在Dockerfile中编写了这行代码,并使用-p运行容器,则端口将在netstat中可见。如果你使用-p但没有编写EXPOSE,则你的端口不会在netstat中列出。


1
很快就到2021年了,这个问题还是没有解决吗? - miu
4个回答

9

回答问题永远不会太晚。

使用netstat -tln而不是netstat -at

如果您为netstat通知--numeric选项,那么回答就非常简单了。通过使用此选项,netstat将打印带有数字的地址,而不是有意义的字符串。然后,您可以像您提到的那样使用grep查找它们。以下是它的工作原理。

[root@A01-R26-I52-155-3002023 ~]# netstat -tl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 localhost.localdom:smux 0.0.0.0:*               LISTEN     
tcp        0      0 localhost.localdo:18121 0.0.0.0:*               LISTEN     
tcp        0      0 localhost.localdo:18122 0.0.0.0:*               LISTEN     
tcp        0      0 localhost.localdo:18123 0.0.0.0:*               LISTEN     
tcp        0      0 localhost.localdo:18124 0.0.0.0:*               LISTEN     
tcp        0      0 localhost.localdo:18125 0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:sunrpc          0.0.0.0:*               LISTEN     
tcp        0      0 localhost.localdo:18928 0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:20080           0.0.0.0:*               LISTEN     
tcp        0      0 A01-R26-:univ-appserver 0.0.0.0:*               LISTEN     
tcp        0      0 A01-R26-:univ-appserver 0.0.0.0:*               LISTEN     
tcp        0      0 localhost.:search-agent 0.0.0.0:*               LISTEN     
tcp        0      0 localhost:mosaicsyssvc1 0.0.0.0:*               LISTEN     
tcp        0      0 A01-R26-I52-155-300:ssh 0.0.0.0:*               LISTEN     
tcp6       0      0 [::]:37611              [::]:*                  LISTEN     
tcp6       0      0 [::]:sunrpc             [::]:*                  LISTEN     
tcp6       0      0 [::]:microsan           [::]:*                  LISTEN     
tcp6       0      0 [::]:commtact-http      [::]:*                  LISTEN     
[root@A01-R26-I52-155-3002023 ~]# netstat -tln
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 127.0.0.1:199           0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:18121         0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:18122         0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:18123         0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:18124         0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:18125         0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:111             0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:18928         0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:20080           0.0.0.0:*               LISTEN     
tcp        0      0 10.217.52.155:1233      0.0.0.0:*               LISTEN     
tcp        0      0 10.218.52.155:1233      0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:1234          0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:1235          0.0.0.0:*               LISTEN     
tcp        0      0 10.217.52.155:22        0.0.0.0:*               LISTEN     
tcp6       0      0 :::37611                :::*                    LISTEN     
tcp6       0      0 :::111                  :::*                    LISTEN     
tcp6       0      0 :::20001                :::*                    LISTEN     
tcp6       0      0 :::20002                :::*                    LISTEN

不要忘记以提升的模式使用sudo运行它。 - Sergey V.

7

以下代码将显示容器中已打开端口及其相应的进程id:

container_name=some_container_name
c_pid=`docker container inspect -f "{{.State.Pid}}" ${container_name}`
nsenter -t ${c_pid} -n netstat -anp

11
请不要只发布代码作为答案,同时提供一个解释,说明你的代码是如何解决问题的。带有解释的答案通常更具质量,并且更有可能获得赞同。 - Mark Rotteveel

5

netstat 应该显示公开的端口。这里有一个例子。

anovil@anovil-Latitude-E6440:docker$ sudo netstat -at|grep 3030
anovil@anovil-Latitude-E6440:docker$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
anovil@anovil-Latitude-E6440:docker$ docker run -d -p 3030:80 httpd:2.4
4310ac5fbdbc7314ab4d23e34099a710a3a8790dcf2c6d0a84202c1de5c9fd30
anovil@anovil-Latitude-E6440:docker$ docker ps
CONTAINER ID        IMAGE               COMMAND              CREATED             STATUS              PORTS                  NAMES
4310ac5fbdbc        httpd:2.4           "httpd-foreground"   3 minutes ago       Up 3 minutes        0.0.0.0:3030->80/tcp   hungry_fermat
anovil@anovil-Latitude-E6440:docker$ sudo netstat -at|grep 3030
tcp6       0      0 [::]:3030               [::]:*                  LISTEN
anovil@anovil-Latitude-E6440:docker$ sudo netstat -tulpn|grep 3030
tcp6       0      0 :::3030                 :::*                    LISTEN      10294/docker-proxy
anovil@anovil-Latitude-E6440:docker$ 

您需要自己验证的一些基本事项:

  1. 您是否使用高级权限运行netstat? 当您非root时,某些内容可能会漏掉
  2. 您的Docker容器是否在预期的同一主机上运行? 使用docker ps进行检查
  3. docker ps中是否列出了端口转发信息? 正如上面所示,您应该能够看到类似于此的内容:0.0.0.0:3030->80/tcp

另外请注意,docker-proxy是在主机上运行的。以上所有命令都假定您在Linux上运行。这已在Ubuntu 15.10上进行了测试。

如果您仍然觉得缺少转发,请回复您的操作系统、Docker版本等信息。

谢谢,


7
谢谢您提供详细的回答。我按照您建议的每一个检查都进行了,将结果写在了我的问题中(请参见更新)。然而,尽管docker端口确实运行正常,但netstat仍未报告这些端口。 - Boris Burkov
3
我感觉这与Docker的“EXPOSE”参数有关。如果在Dockerfile中编写此行并使用“-p”运行容器,则端口将在netstat中可见。如果您使用“-p”但未编写“EXPOSE”,则netstat不会列出您的端口。还没有测试这个假设。 - Boris Burkov
当我使用sudo命令运行netstat时,它对我起作用了。我忘记了docker正在使用特权权限运行。 - mavi

0

它们已列出,只是不像你想象的那样。如果你正在寻找ipv4监听端口,你将看不到它(除非我相信如果你同时使用EXPOSE和发布(-p)机制),但你将看到一个基于ipv6的docker代理,例如MySQL容器:

netstat -tlpn4
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp6       0      0 :::3306                 :::*                    LISTEN      9608/docker-proxy

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