当Docker使用端口时,Node.js不会抛出EADDRINUSE

时间:2018-01-15 14:40:51

标签: javascript node.js docker

我正在Node.js中编写HTTP服务器。我想确保在我想要使用的端口已经分配时出现错误(应该是EADDRINUSE错误)。所以我的代码看起来像这样:

const http = require('http');

http.createServer((req, res) => {
  res.end('Hello world');
}).listen(3000, {
  console.log('Server running.');
}).on('error', err => {
  console.log(err);
});

现在,当我运行此服务器一次时,它可以运行,并且服务器在端口3000上运行。当我第二次运行服务器时,它会失败并出现错误,如预期的那样。

到目前为止,非常好。

现在我启动一个使用端口3000的Docker容器(我正在使用Docker for macOS 17.12)。当我现在运行我的Node.js应用程序时,我收到服务器正在运行的消息,但它没有响应 - 显然它没有运行?

如果我改变了行

}).listen(3000, {

}).listen(3000, '0.0.0.0', {

然后我实际收到错误消息。那么,Docker的情况有何不同?为什么服务器可以在没有错误的情况下启动,但为什么它无法访问呢? ...?

PS:我原本以为Docker可以绑定到IPv4,Node.js可以绑定到IPv6,但不管我是访问http://localhost:3000http://127.0.0.1:3000还是http://[::1]:3000 - 它始终是回复的Docker容器。

PPS:特定的Docker容器并不重要 - 我得到了使用端口3000的任何 Docker容器的行为。如果要重现它,可以使用docker run -d -p 3000:80 nginx。< / p>

1 个答案:

答案 0 :(得分:1)

因为您在容器中运行app,所以docker会为每个容器分配单独的虚拟网络接口。您实际上可以在图片中看到它们(docker run -it my_node_container /bin/bashifconfig)。因此,当您未指定0.0.0.0时,它将绑定到本地接口,而该接口未暴露在容器外部。如果绑定到0.0.0.0,它现在暴露在容器之外(或者不是,根据您的网络配置,您必须映射端口或运行-net=host)。所以现在它可以与在同一端口上监听的其他应用程序冲突。