英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论