在 AWS Elastic Beanstalk 应用程序中运行 Tomcat Docker 时的端口转发

Posted

技术标签:

【中文标题】在 AWS Elastic Beanstalk 应用程序中运行 Tomcat Docker 时的端口转发【英文标题】:Port forwarding in when running a Tomcat Docker in an AWS Elastic Beanstalk application 【发布时间】:2015-03-29 12:28:44 【问题描述】:

我有一个 Tomcat 7.0 webapp 在 AWS Elastic Beanstalk (EB) 上的 docker 容器中运行(我按照教程 here 操作)。

当我浏览到我的 EB 网址 myapplication.elasticbeanstalk.com 时,我得到了一个由 nginx 提供服务的 502 Bad Gateway。所以很明显我的 80 端口没有转发到我的容器。当我浏览到 myapplication.elasticbeanstalk.com:8888(我在 Dockerfile 中公开的另一个端口)时,连接被拒绝(ERR_CONNECTION_REFUSED)。于是我通过 SSH 连接到 AWS 实例并查看了 docker 日志,显示我的 Tomcat 服务器已成功启动,但显然还没有处理任何请求。

有人知道我的 8888 端口似乎没有转发到我的容器吗?

执行命令(在 AWS 实例上):

sudo docker ps -a

给予:

CONTAINER ID        IMAGE                              COMMAND             CREATED             STATUS                     PORTS                        NAMES     
c353e236da7a        aws_beanstalk/current-app:latest   "catalina.sh run"   28 minutes ago      Up 13 minutes              80/tcp, 8080/tcp, 8888/tcp   sharp_leakey  

显示 80、8080 和 8888 端口在 docker 容器上处于打开状态。

我的 Dockerfile 相当简单:

FROM tomcat:7.0

EXPOSE 8080
EXPOSE 8888
EXPOSE 80

而我的 Dockerrun.aws.json 文件是:


  "AWSEBDockerrunVersion": "1",
  "Image": 
    "Name": "myusername/mycontainer-repo"
  ,
  "Authentication": 
    "Bucket": "mybucket",
    "Key": "docker/.dockercfg"
  ,
  "Ports": [
    
      "ContainerPort": "8888"
    
  ]

有人知道我哪里出错了吗? 我什至不知道从哪里看这一点。

此外,我的实例的 AWS 安全组在端口 80、8080 和 8888 上打开。 任何建议将不胜感激!我在这里不知所措。

更新 1:

小更新,虽然我仍然遇到问题。 SSH 连接到我的 AWS EB 实例后,我检查了 Docker 容器以获取容器的 IP:

sudo docker inspect c353e236da7a

这给了我172.17.0.6的IP。

然后,我再次从 AWS 实例运行 curl 命令:

curl 172.17.0.6:8080/homepage 

有效,并返回主页的 html!但是,curl 172.17.0.6:8888/homepage 不起作用(所以我不确定 "ContainerPort" : "8888"Dockerrun.aws.json 文件中的含义)。

但是,我仍然有一个问题,为什么我的:8080 请求没有被转发到容器 Tomcat 网络服务器?如上所述,myapplication.elasticbeanstalk.com:8080/homepage 仍然收到拒绝连接 (ERR_CONNECTION_REFUSED)。

【问题讨论】:

【参考方案1】:

myapplication.elasticbeanstalk.com 是负载均衡器,而不是您的实例。 Elastic beanstalk 启动负载均衡器来自动扩展您的实例。因此,当您连接到myapplication.elasticbeanstalk.com:8888 时,您实际上是在连接到仅打开端口 80 的实例。然后负载均衡器将流量转发到侦听端口 8080 的实例。

您应该可以通过不带端口的 url 访问您的 Web 应用程序:myapplication.elasticbeanstalk.com

这不起作用的原因是因为你告诉你的 docker 容器使用端口 8080,但告诉 Beanstalk 转发到端口 8888。当然,你所有的端口都是开放的,但 tomcat 只在端口 8080 上运行。

dockerrun.aws.json 中的端口部分不会告诉您的应用程序要在哪个端口上运行,它会告诉负载均衡器要转发到哪个端口。

Ports –(指定 Image 键时需要)列出要在 Docker 容器上公开的端口。 AWS Elastic Beanstalk 使用 ContainerPort 值将 Docker 容器连接到主机上运行的反向代理。

您可以指定多个容器端口,但 AWS Elastic Beanstalk 仅使用第一个端口将您的容器连接到主机的反向代理并路由来自公共 Internet 的请求。

如here所见。

或者,换句话说,您告诉 beanstalk 转发到的 8888 工作正常,但您的应用程序实际上在端口 8080 上运行。您应该更改 dockerrun.aws.json 以使用端口 8080

【讨论】:

【参考方案2】:

我通过修复 nginx 的监听端口来完成这项工作。 因此,您必须将 .ebextensions 目录添加到应用程序的根目录中,并将配置文件放在这里(在我的示例中为 00-bypass-nginx-proxy.config):

files:
  "/tmp/change_nginx_port.sh":
  mode: "000755"
  owner: root
  group: root
  content: |
    #!/bin/sh

    # change listen port from 80 to 8761
    sed -i '7s/.*/        listen 8761;/' /etc/nginx/sites-available/elasticbeanstalk-nginx-docker-proxy.conf

    # restart nginx
    service nginx restart

container_commands:
  00setup-nginx:
    command: "/tmp/change_nginx_port.sh"

您的服务现在将在端口 8761 上可用。注意脚本的sed 部分,有硬编码的行号,可能因您的环境而异。

【讨论】:

以上是关于在 AWS Elastic Beanstalk 应用程序中运行 Tomcat Docker 时的端口转发的主要内容,如果未能解决你的问题,请参考以下文章

Elastic Beanstalk 不会自动从 ECR 更新图像

Amazon Elastic BeanStalk 错误:无法创建 AWS Elastic Beanstalk 应用程序版本

[AWS] Elastic Beanstalk

如何在 aws elastic beanstalk 环境实例启动上运行 shell 脚本

无法在 AWS Elastic Beanstalk 中创建环境?

在 Elastic Beanstalk(AWS) 中守护 Celerybeat