我正在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:3000,http://127.0.0.1:3000还是http://[::1]:3000 - 它始终是回复的Docker容器。 PPS:特定的Docker容器并不重要 - 我得到了使用端口3000的任何 Docker容器的行为。如果要重现它,可以使用docker run -d -p 3000:80 nginx
。< / p>
答案 0 :(得分:1)
因为您在容器中运行app,所以docker会为每个容器分配单独的虚拟网络接口。您实际上可以在图片中看到它们(docker run -it my_node_container /bin/bash
,ifconfig
)。因此,当您未指定0.0.0.0时,它将绑定到本地接口,而该接口未暴露在容器外部。如果绑定到0.0.0.0,它现在暴露在容器之外(或者不是,根据您的网络配置,您必须映射端口或运行-net=host
)。所以现在它可以与在同一端口上监听的其他应用程序冲突。