Amazon AWS ECS Docker 端口绑定不正确

Amazon AWS ECS Docker Port not binding correctly

我正在使用 ECS 优化的 ECS 映像并使用 ECS 进行部署。

所以如果我 bash 进入容器并且 curl localhost 我得到预期的输出(预期在端口 80 上),这工作正常。

那么如果我运行docker ps 我得到以下输出

CONTAINER ID   IMAGE                              COMMAND             CREATED             STATUS              PORTS                        NAMES
1234           orgname/imagename:release-v0.3.1   "npm start"         53 minutes ago      Up 53 minutes       0.0.0.0:80->80/tcp           ecs-myname-1234`

这表明正在按预期映射端口 80。 (我也看到了 Amazon ECS 代理,但在上面发布的并不重要)

然后我可以 运行 netstat -tulpn | grep :80 我得到以下输出

(No info could be read for "-p": geteuid()=500 but you should be root.)
tcp        0      0 :::80                       :::*                        LISTEN      -  

然后作为 root 我 运行 sudo netstat -tulpn | grep :80 并且我得到以下输出

tcp        0      0 :::80                       :::*                        LISTEN      21299/docker-proxy  

这让我觉得它只在 IPv6 接口上侦听?我作为本地主机的主机记录是 127.0.0.1 这就是为什么当我在主机上 运行 curl localhostcurl 127.0.0.1 我得到 curl: (56) Recv failure: Connection reset by peer

我还检查了安全组和网络 ACLS(并不是说它们应该对本地主机有影响)...

如有任何想法,我们将不胜感激!

编辑: 为了更好地衡量(有些人建议当 ipv6 可用时 netstat 只显示 ipv6 而不是 ipv4。我也有 运行 这个命令 lsof -OnP | grep LISTEN 给出以下输出

sshd       2360     root    3u     IPv4              10256       0t0        TCP *:22 (LISTEN)
sshd       2360     root    4u     IPv6              10258       0t0        TCP *:22 (LISTEN)
sendmail   2409     root    4u     IPv4              10356       0t0        TCP 127.0.0.1:25 (LISTEN)
exe        2909     root    4u     IPv4              13802       0t0        TCP 127.0.0.1:51678 (LISTEN)
exe       21299     root    4u     IPv6              68069       0t0        TCP *:80 (LISTEN)
exe       26395     root    4u     IPv6              89357       0t0        TCP *:8080 (LISTEN)

我 运行 在使用 bridge 网络模式时遇到了这个问题。我还没有找到解决方案。但是,我使用了两种解决方法。

解决方法

对我来说最简单的方法是在我的 ECS 任务定义中将 NetworkMode 更改为 host

或者,您可以使用 Application Load Balancer.

消除了解或关心端口映射方式的需要

网络模式

bridge 通过 docker-代理将容器端口映射到主机上的另一个端口(可能不同)。这是我在 ECS 中遇到的问题。

host 允许容器直接在主机上打开一个端口,而不需要代理。缺点是同一容器的实例不能 运行 在同一主机上而不导致端口冲突。

awsvpc 类似于 host,除了它映射到 VPC 中的 ENI 而不是主机 IP 上的端口。

none 听起来就是这样。

应用程序负载均衡器

发布此答案后,我的项目要求发生了变化。我还没有机会回去直接测试桥接模式下的端口映射。但是,我现在正在使用 Application Load Balancer 来提供对我的容器的访问。

使用 ALB 时,您根本不必担心主机端口。相反,您的 ECS 服务会自动将您的容器作为目标添加到给定的 ALB 目标组。本文档详细介绍了如何执行此操作:

https://docs.aws.amazon.com/AmazonECS/latest/developerguide/service-load-balancing.html

这里不做详细说明,因为它不是对端口绑定问题的直接回答。


有趣的是,ECS 的网络模式是在您提出问题后 5 天公布的:

公告:https://aws.amazon.com/about-aws/whats-new/2016/08/amazon-ec2-container-service-now-supports-networking-modes-and-memory-reservation/

网络模式文档:https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_RegisterTaskDefinition.html#ECS-RegisterTaskDefinition-request-networkMode

希望这个回答能帮助其他一些 Google 员工。 注意:如果我弄清楚如何让 bridge 模式在 ECS 中正常工作,我会更新这个答案。

我有一个类似的问题,但我在 docker 中是 运行 Java,它仅在 IPv6 端口上绑定。原来是 Java 相关。关于此的更多信息 here