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 localhost
或 curl 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 天公布的:
希望这个回答能帮助其他一些 Google 员工。 注意:如果我弄清楚如何让 bridge
模式在 ECS 中正常工作,我会更新这个答案。
我有一个类似的问题,但我在 docker 中是 运行 Java,它仅在 IPv6 端口上绑定。原来是 Java 相关。关于此的更多信息 here
我正在使用 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 localhost
或 curl 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 天公布的:
希望这个回答能帮助其他一些 Google 员工。 注意:如果我弄清楚如何让 bridge
模式在 ECS 中正常工作,我会更新这个答案。
我有一个类似的问题,但我在 docker 中是 运行 Java,它仅在 IPv6 端口上绑定。原来是 Java 相关。关于此的更多信息 here