无法连接到某些镜像的Docker容器端口。

huangapple go评论54阅读模式
英文:

Cant connect to docker container port of some images

问题

尝试调查我的 Docker 容器问题。我曾花了一整天认为问题出在 Node.js 代码中(它有一个服务器,我试图连接到这个服务器)。

经过调查,我发现了对我来说很有趣的事情。

例如,让我们运行一些测试 Docker 镜像:

docker run -p 888:888 -it ubuntu:16 /bin/bash

之后,准备并安装一个"简单的服务器来监听我们的端口":

apt-get update
apt-get install -y netcat
nc -l 888

之后,我尝试从我的系统上运行 telnet localhost 888,但得到了 telnet: connect to address 127.0.0.1: Connection refused 的错误。对于 nodejs 镜像也是一样的。

但如果你尝试使用,例如,nginx 容器 -

docker run -p 888:888 -it nginx /bin/bash

我会成功:

$ telnet 127.0.0.1 888
Trying 127.0.0.1...
Connected to localhost.

这是如何可能的,我漏掉了什么?为什么我可以在 nginx 中绑定和使用任何端口,但在其他镜像中不行?

英文:

Trying investigate my issue with docker container. I lost a day when I thought that issue is in nodejs code (it has server and I am trying to connect to this server).

After investigations I found interesting thing for me.

For example - Lets run some test docker image:

docker run -p 888:888 -it ubuntu:16 /bin/bash

After that, prepare and install "simple server to listen our port":

apt-get update
apt-get install -y netcat
nc -l 888

After that I going to try to telnet localhost 888 from my system and got telnet: connect to address 127.0.0.1: Connection refused. The same with nodejs image.

But if you try to use, for example, nginx container -

docker run -p 888:888 -it nginx /bin/bash

I will be successfull:

$telnet 127.0.0.1 888 
Trying 127.0.0.1...
Connected to localhost.

How it is possible, what I am missing? Why I can bind and use any port in nginx but not for other images?

答案1

得分: 0

当你运行 nc -l 888 时,你创建了一个监听 IPv4 连接的端口。如果我们运行 ss -tln,我们会看到:

State   Recv-Q  Send-Q     本地地址:端口     对端地址:端口  进程
LISTEN  0       1                0.0.0.0:888           0.0.0.0:*

当你在主机上运行 telnet localhost 888 时,很有可能它试图连接到IPv6的本地地址 ::1。如果你尝试连接一个仅支持IPv4的套接字,连接将失败。

如果你明确使用IPv4环回地址,可以输入 telnet 127.0.0.1 888,它应该按预期工作。


如果你通过添加 -6 参数启用了 nc 中的IPv6支持:

nc -6 -l 8888

那么你将得到一个同时监听IPv4和IPv6连接的套接字:

State   Recv-Q  Send-Q     本地地址:端口     对端地址:端口  进程
LISTEN  0       1                      *:888                 *:*

如果你尝试使用 telnet localhost 888 连接到这个套接字,它将按预期工作(telnet 127.0.0.1 888 也将正常工作)。

大多数程序(如 nginx)默认情况下会打开多协议套接字,因此这通常不是一个问题。

英文:

When you run nc -l 888, you are creating a port that is listening explicitly for IPv4 connections. If we run ss -tln, we will see:

State   Recv-Q  Send-Q     Local Address:Port     Peer Address:Port  Process
LISTEN  0       1                0.0.0.0:888           0.0.0.0:*

When you run telnet localhost 888 on your host, there's a good chance it's trying to connect to the IPv6 localhost address, ::1. This connection fails if you're trying to connect an IPv4-only socket.

If you explicitly use the IPv4 loopback address by typing telnet 127.0.0.1 888, it should work as expected.


If you enable IPv6 support in nc by adding the -6 parameter:

nc -6 -l 8888

Then you get a socket that listen for both IPv4 and IPv6 connections:

State   Recv-Q  Send-Q     Local Address:Port     Peer Address:Port  Process
LISTEN  0       1                      *:888                 *:*

And if you attempt to connect to this socket using telnet localhost 888, it will work as expected (as will telnet 127.0.0.1 888).

Most programs (like nginx) open multi-protocol sockets by default, so this isn't normally an issue.

huangapple
  • 本文由 发表于 2023年2月19日 11:46:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/75497856.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定