首页 > 解决方案 > 运行 apache 时可以连接到 docker 容器,但在端口 80 上运行 netcat 时不能

问题描述

我正在使用 Debian 软件包运行 Debian 服务器(稳定) 。这docker.io是 Debian 分发的服务器,而不是 Docker 开发人员提供的服务器。由于docker.io仅在 sid 中​​可用,因此我已从那里安装 ( apt install -t unstable docker.io)。

我的防火墙确实允许与 docker 容器之间的连接:

$ sudo ufw status
(...)
Anywhere                   ALLOW       172.17.0.0/16             
172.17.0.0/16              ALLOW       Anywhere                  

我也有这个/etc/ufw/before.rules

*nat
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -s 172.17.0.0/16    -o eth0 -j MASQUERADE

所以 - 我已经创建了一个图像

$ sudo debootstrap stable ./stable-chroot http://deb.debian.org/debian > /dev/null
$ sudo tar -C stable-chroot -c . | docker import - debian-stable

然后启动一个容器并安装了 apache2 和 netcat。主机上的 1111 端口将被重定向到容器上的 80 端口:

$ docker run -ti -p 1111:80 debian-stable bash
root@dc4996de9fe6:/# apt update
(... usual output from apt update ...)
root@dc4996de9fe6:/# apt install apache2 netcat
(... expected output, installation successful ...)
root@dc4996de9fe6:/# service apache2 start
root@dc4996de9fe6:/# service apache2 status
[ ok ] apache2 is running.

我可以从主机连接到 apache 服务器:

$ curl 127.0.0.1:1111
(... HTML from the Debian apache placeholder page ...)
$ telnet 127.0.0.1 1111
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.

它等待我输入(如果我输入GET /,我会得到 Debian apache 占位符页面)。好的。如果我在容器内停止 apache,

root@06da401a5724:/# service apache2 stop
[ ok ] Stopping Apache httpd web server: apache2.
root@06da401a5724:/# service apache2 status
[FAIL] apache2 is not running ... failed!

然后到主机上的端口 1111 的连接将被拒绝(如预期的那样):

$ telnet 127.0.0.1 1111
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
Connection closed by foreign host.

现在,如果我在容器上启动 netcat,监听 80 端口:

root@06da401a5724:/# nc -l 172.17.0.2 80

然后我无法从主机连接!

$ telnet localhost 1111
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Connection closed by foreign host.

如果我nc -l 127.0.0.1 80在容器中尝试,也会发生同样的情况。

会发生什么?apache 和 netcat 都在监听 80 端口。我错过了什么?我会很感激任何提示...

更新:如果我试试这个:

root@12b8fd142e00:/# nc -vv -l -p 80
listening on [any] 80 ...
172.17.0.1: inverse host lookup failed: Unknown host
invalid connection to [172.17.0.2] from (UNKNOWN) [172.17.0.1] 54876

然后它起作用了!

现在很奇怪......ifconfig容器内告诉我它有 IP 172.17.0.2,但我只能使用 netcat 绑定到172.17.0.1

root@12b8fd142e00:/# ifconfig 
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.2  netmask 255.255.0.0  broadcast 0.0.0.0
        inet6 fe80::42:acff:fe11:2  prefixlen 64  scopeid 0x20<link>

而 Apache 似乎想要172.17.0.2

2AH00558: apache2: Could not reliably determine the server's fully qualified domain name, using 172.17.0.2. Set the 'ServerName' directive globally to suppress this message

但它实际上使用172.17.0.1

root@12b8fd142e00:/# netstat
Active Internet connections (w/o servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 12b8fd142e00:http       172.17.0.1:54942        TIME_WAIT  
tcp        0      0 12b8fd142e00:39528      151.101.48.204:http     TIME_WAIT  

标签: docker

解决方案


Apache 没有监听172.17.0.1,这是主机的地址(在 docker 桥中)。

在 netstat 输出中,本地地址已解析为12b8fd142e00. 使用-n带有 netstat 的选项来查看未解析的(数字)地址(例如netstat -plnet查看监听套接字)。172.17.0.1是连接到 Apache 的外部地址(它确实是主机)。

netstat 输出的最后一行显示某个进程连接到 151.101.48.204:80,可能是为了发出 HTTP 请求。您可以使用 . 查看进程的 PID/名称netstat -p


推荐阅读