Docker端口未公开


78

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

Docker文件

FROM node:latest
RUN apt-get -y update
ADD example.js .
EXPOSE 1337   
CMD node example.js

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/');

现在建立图像

$ docker build -t node_server .

现在在容器中运行

$ docker run -p 1337:1337 -d node_server  
$ 5909e87302ab7520884060437e19ef543ffafc568419c04630abffe6ff731f70

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

$ 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

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

$ docker exec -it 5909e87302ab7520884060437e19ef543ffafc568419c04630abffe6ff731f70 /bin/bash 

并在容器命令行中输入:

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

看起来不错吧?

问题

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

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

我已经尝试过的事情:

  • 带着--expose 1337旗帜跑

您不会“以--expose”运行。使用EXPOSE指令构建映像,然后使用--publish(或-p)运行。请参阅下面的答案。
VonC

Answers:


117

端口正确暴露,但是服务器正在侦听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');

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

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');

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


3
收听0.0.0.0看起来很奇怪,但并不立刻明白这意味着什么。不过,它似乎是默认值,因此您可以从listen()函数中忽略该参数,我认为这样更容易掌握nodejs.org/api/…–
Davos

5
在0.0.0.0上侦听意味着“在所有接口上监听”。它通常过于矫kill,有时出于安全考虑,但通常无害。在Docker容器内有意义。
Jim Stewart

1
非常感谢,此解决方案解决了在docker中运行的任何类型的服务器(例如java或node.js express服务器)的问题。该接口无论如何都必须为:0.0.0.0,其中端口是使用-P $PORT:$PORT/tcp选项导出的端口,因此通常服务器会export HOST=0.0.0.0在运行时进行检查。
loretoparisi

1
非常感谢您-花了我无尽的时间来解决它!
readikus

34

将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公开,并发布到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

或者,如上所述,使您的服务器侦听来自任何IP的连接:IP0.0.0.0广播地址或零网络


谢谢您的评论,但正如我上面提到的,我已经尝试添加EXPOSE 1337,但它也不起作用
Assaf Shomer

@AssafShomer两者都需要,这就是我回答的全部内容
VonC

@AssafShomer我已经编辑了答案,以使这一点更清楚。
VonC

2
谢谢,当然,我都尝试过。即:使用EXPOSE 1337构建并使用-p 1337:1337运行,但仍然没有。我更改了问题以反映这一点。
阿萨夫·肖默

@AssafShomer您是直接在Linux上,还是通过Windows或Mac上的boot2docker VM使用docker?
VonC
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.