Docker端口未公开

Ass*_*mer 48 port networking docker

我在Docker中设置了一个简单的节点服务器.

Dockerfile

FROM node:latest
RUN apt-get -y update
ADD example.js .
EXPOSE 1337   
CMD node example.js
Run Code Online (Sandbox Code Playgroud)

example.js

var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n'+new Date);
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');
Run Code Online (Sandbox Code Playgroud)

现在构建图像

$ docker build -t node_server .
Run Code Online (Sandbox Code Playgroud)

现在在容器中运行

$ docker run -p 1337:1337 -d node_server  
$ 5909e87302ab7520884060437e19ef543ffafc568419c04630abffe6ff731f70
Run Code Online (Sandbox Code Playgroud)

验证容器是否正在运行并且端口已映射:

$ docker ps  

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
5909e87302ab        node_server         "/bin/sh -c 'node exa"   7 seconds ago       Up 6 seconds        0.0.0.0:1337->1337/tcp   grave_goldberg
Run Code Online (Sandbox Code Playgroud)

现在让我们附加到容器并验证服务器是否正在运行:

$ docker exec -it 5909e87302ab7520884060437e19ef543ffafc568419c04630abffe6ff731f70 /bin/bash 
Run Code Online (Sandbox Code Playgroud)

并在容器命令行中输入:

root@5909e87302ab:/# curl http://localhost:1337
Hello World
Mon Feb 15 2016 16:28:38 GMT+0000 (UTC)
Run Code Online (Sandbox Code Playgroud)

看起来不错?

问题

当我在主机上执行相同的curl命令(或使用我的浏览器导航到http:// localhost:1337)时,我什么也看不见.

知道为什么容器和主机之间的端口映射不起作用?

我已经尝试过的事情:

  • --expose 1337旗帜一起运行

Chr*_*nel 72

您的端口正确暴露,但您的服务器正在侦听127.0.0.1容器内部的连接:

http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n'+new Date);
}).listen(1337, '127.0.0.1');
Run Code Online (Sandbox Code Playgroud)

您需要像这样运行您的服务器:

http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n'+new Date);
}).listen(1337, '0.0.0.0');
Run Code Online (Sandbox Code Playgroud)

请注意0​​.0.0.0而不是127.0.0.1.

  • 在0.0.0.0上收听意味着“在所有接口上收听”。它通常过于矫kill,有时出于安全考虑,但通常无害。在Docker容器内有意义。 (3认同)
  • 收听0.0.0.0看起来很奇怪,但并不立刻明白这意味着什么。不过,它似乎是默认值,因此您可以从`listen()`函数中忽略该参数,我认为它更容易理解https://nodejs.org/api/net.html#net_server_listen_port_host_backlog_callback (2认同)

Von*_*onC 28

将EXPOSE 1337添加到docker文件中

EXPOSE强制性 如果要将该端口"暴露"到其他容器中.

正如BMitch评论:

Expose不需要发布端口或通过共享docker网络将容器连接到容器.
它是用于发布所有端口-P并检查图像/容器的元数据.

所以:

--expose 1337旗帜一起运行

不完全是:你需要泊坞窗运行-p 1337:1337

你需要:

  • EXPOSE它中的指令构建一个图像(用于-P)
  • 或者使用主机上发布的端口运行它-p 1337:1337

测试curl http://localhost:1337是在容器内完成的(不需要EXPOSE或需要发布).
如果您希望它可以从Linux主机运行,您需要EXPOSE+-P 或者需要它-p 1337:1337.
无论是.

声明它单独暴露有利于记录意图,但不会单独做任何事情.

例如:

https://i.stack.imgur.com/wmKgd.png

在该图中,8080是EXPOSE,发布到Linux主机8888.
如果该Linux主机不是实际主机,则需要将相同端口快速发送到实际主机.请参阅" 如何从浏览器访问在docker容器中运行的tomcat? ".

如果localhost无法从Linux主机运行,请尝试其IP地址:

CID=$(docker run -p 1337:1337 -d node_server)
CIP=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' ${CID})
curl http://${CIP}:1337
Run Code Online (Sandbox Code Playgroud)

或者,正如上面提到的,让你的服务器从任何IP来连接听:0.0.0.0这是广播地址或零网络.

  • `Dockerfile` 中的 `EXPOSE` 完全没有必要。它纯粹用作文档。这是一个好主意,表明意图,但它也具有误导性,因为它根本没有做任何事情。它也可能是一个评论。 (4认同)
  • 谢谢,当然,我都尝试过。即:使用EXPOSE 1337进行构建,并使用-p 1337:1337运行,仍然一无所获。我更改了问题以反映这一点。 (2认同)