无法将多容器 docker 部署到 ElasticBeanstalk

Posted

技术标签:

【中文标题】无法将多容器 docker 部署到 ElasticBeanstalk【英文标题】:Failed to deploy multi-containers docker to ElasticBeanstalk 【发布时间】:2021-10-26 02:04:14 【问题描述】:

我试图将多容器 docker 部署到 Elastic Beanstalk 中。但它不起作用。我尝试使用正在运行的 docker-compose 在本地运行。

下面是我的 Dockerrun.aws.json 和 docker-compose.yml

docker-compose.yml

version: '3'

services:
   nginx:
      image: nginx:alphine
      restart: always
      ports:
      - 80:80
      volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d
      depends_on:
      - sbapi
   db:
      image: mysql:latest
      environment:
      - MYSQL_ROOT_PASSWORD=P@ssw0rd
      - MYSQL_DATABASE=sbapi
      - MYSQL_USER=user
      - MYSQL_PASSWORD=password
      ports:
      - 3306:3306
      restart: always
      volumes:
      - mysql-data:/var/lib/mysql
   sbapi:
      image: sbapi
      build:
         context: ./
         dockerfile: Dockerfile
      ports:
      - 8080:8080
      restart: always
      volumes:
      - ./app:/app
      depends_on:
      - db
      
volumes:
  mysql-data:

Dockerrun.aws.json

 
   "AWSEBDockerrunVersion":2,
   "containerDefinitions":[
      
         "name":"db",
         "hostname": "db",
         "image":"mysql:latest",
         "essential":true,
         "memory":512,
         "environment": [
            
                "name": "MYSQL_ROOT_PASSWORD",
                "value": "P@ssw0rd"
            ,
            
                "name": "MYSQL_DATABASE",
                "value": "sbapi"
            ,
            
                "name": "MYSQL_USER",
                "value": "user"
            ,
            
                "name": "MYSQL_PASSWORD",
                "value": "password"
            
         ],
         "portMappings":[
            
               "hostPort":3306,
               "containerPort":3306
            
         ],
         "mountPoints":[
            
               "containerPath":"/var/lib/mysql",
               "sourceVolume":"mysql-data"
            
         ]
      ,
      
         "name":"sbapi",
         "hostname": "sbapi",
         "essential":true,
         "image":"xxxxxxxxxxxxxxxx.dkr.ecr.ap-southeast-1.amazonaws.com/sbapi",
         "memory":512,
         "portMappings":[
            
               "hostPort":8080,
               "containerPort":8080
            
         ],
         "links": [
            "db"
         ]
      ,
      
         "name":"nginx",
         "image":"nginx:alpine",
         "essential":true,
         "memory": 128,
         "portMappings":[
            
               "hostPort":80,
               "containerPort":80
            
         ],
         "mountPoints":[
            
               "containerPath":"/etc/nginx/conf.d",
               "sourceVolume":"nginx-data"
            
         ],
         "links":[
            "sbapi"
         ]
      
   ],
   "family": "",
   "volumes":[
      
         "host":,
         "name":"mysql-data"
      ,
      
         "name": "nginx-data",
         "host": 
            "sourcePath": "/var/app/current/nginx/conf.d"
         
      
   ]

这是我的 nginx.stouterr.log。不知道会不会自动关机。

/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: /etc/nginx/conf.d/default.conf differs from the packaged version
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2021/08/26 00:21:11 [notice] 1#1: using the "epoll" event method
2021/08/26 00:21:11 [notice] 1#1: nginx/1.21.1
2021/08/26 00:21:11 [notice] 1#1: built by gcc 8.3.0 (Debian 8.3.0-6) 
2021/08/26 00:21:11 [notice] 1#1: OS: Linux 4.14.238-125.422.amzn1.x86_64
2021/08/26 00:21:11 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 133489:133489
2021/08/26 00:21:11 [notice] 1#1: start worker processes
2021/08/26 00:21:11 [notice] 1#1: start worker process 30
2021/08/26 00:21:11 [notice] 1#1: start worker process 31
2021/08/26 00:21:11 [notice] 1#1: signal 3 (SIGQUIT) received, shutting down
2021/08/26 00:21:11 [notice] 30#30: gracefully shutting down
2021/08/26 00:21:11 [notice] 30#30: exiting
2021/08/26 00:21:11 [notice] 30#30: exit
2021/08/26 00:21:11 [notice] 31#31: gracefully shutting down
2021/08/26 00:21:11 [notice] 31#31: exiting
2021/08/26 00:21:11 [notice] 31#31: exit
2021/08/26 00:21:11 [notice] 1#1: signal 17 (SIGCHLD) received from 30
2021/08/26 00:21:11 [notice] 1#1: worker process 30 exited with code 0
2021/08/26 00:21:11 [notice] 1#1: worker process 31 exited with code 0
2021/08/26 00:21:11 [notice] 1#1: exit

我检查了 ECS,一开始有 3 个容器正在运行。但后来,所有状态都变为停止,并再次产生另一个新任务。

我还收到错误“连接被拒绝”,无法从我的 Spring Boot 应用程序连接 MySQL。

Caused by: com.mysql.cj.exceptions.CJCommunicationsException: Communications link failure

The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) ~[na:na]
    at java.base/java.lang.reflect.Constructor.newInstance(Unknown Source) ~[na:na]
    at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:61) ~[mysql-connector-java-8.0.23.jar!/:8.0.23]
    at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:105) ~[mysql-connector-java-8.0.23.jar!/:8.0.23]
    at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:151) ~[mysql-connector-java-8.0.23.jar!/:8.0.23]
    at com.mysql.cj.exceptions.ExceptionFactory.createCommunicationsException(ExceptionFactory.java:167) ~[mysql-connector-java-8.0.23.jar!/:8.0.23]
    at com.mysql.cj.protocol.a.NativeSocketConnection.connect(NativeSocketConnection.java:89) ~[mysql-connector-java-8.0.23.jar!/:8.0.23]
    at com.mysql.cj.NativeSession.connect(NativeSession.java:144) ~[mysql-connector-java-8.0.23.jar!/:8.0.23]
    at com.mysql.cj.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:953) ~[mysql-connector-java-8.0.23.jar!/:8.0.23]
    at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:823) ~[mysql-connector-java-8.0.23.jar!/:8.0.23]
    ... 58 common frames omitted
Caused by: java.net.ConnectException: Connection refused (Connection refused)
    at java.base/java.net.PlainSocketImpl.socketConnect(Native Method) ~[na:na]
    at java.base/java.net.AbstractPlainSocketImpl.doConnect(Unknown Source) ~[na:na]
    at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source) ~[na:na]
    at java.base/java.net.AbstractPlainSocketImpl.connect(Unknown Source) ~[na:na]
    at java.base/java.net.SocksSocketImpl.connect(Unknown Source) ~[na:na]
    at java.base/java.net.Socket.connect(Unknown Source) ~[na:na]
    at com.mysql.cj.protocol.StandardSocketFactory.connect(StandardSocketFactory.java:155) ~[mysql-connector-java-8.0.23.jar!/:8.0.23]
    at com.mysql.cj.protocol.a.NativeSocketConnection.connect(NativeSocketConnection.java:63) ~[mysql-connector-java-8.0.23.jar!/:8.0.23]
    ... 61 common frames omitted

这是我的 application.properties

spring.datasource.url=jdbc:mysql://db:3306/sbapi?allowPublicKeyRetrieval=true&useSSL=false
spring.datasource.username=user
spring.datasource.password=password

server.port = 8080

从本地运行 docker-compose up 时,我能够访问 API。但是,在部署到 Elastic Beanstalk 时,它不起作用。不知道是哪一部分出了问题,我很好奇为什么ECS会停止自己并一次又一次地重新生成新任务?

【问题讨论】:

ECS 服务有事件选项卡来检查消息。此外,如果任务停止,您可以在 ECS 控制台中查看其详细信息,并且通常还可以找到错误消息。 是的,我已经检查过了,我什至进入 EC2 运行 docker。不知何故,我收到此错误原因:java.net.UnknownHostException:db:系统错误。 我试过 docker ps 我可以看到 mysql 正在运行。 59d6bf11b1ba mysql:latest "docker-entrypoint.s…" 34 分钟前 Up 34 分钟 0.0.0.0:3306->3306/tcp, 33060/tcp 我尝试 exec 进入 mysql 容器并检查主机 root@db:/etc# cat hosts 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00: :0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters 172.17.0.2 db 如果你有 docker compose,为什么要使用Dockerrun.aws.json 【参考方案1】:

EB 的 Docker 平台支持 docker-compose.yml,如 Docker environment with Docker Compose 中所述:

创建 docker-compose.yml 文件以将 Docker 映像从托管存储库部署到 Elastic Beanstalk。如果您的所有部署都来自公共存储库中的图像,则不需要其他文件。

所以你可能只需要Dockerrun.aws.json v3 到enable access to private docker registry。

【讨论】:

我的图像在 ECR 中。所以我还需要 dockerrun 对吗? @EinnHann 应通过 EB 实例角色启用对 ECR 的访问。所以不需要dockerrun。 这意味着在我的 docker-compose 中我可以在 ECR 中指定 docker 镜像? @EinnHann 我相信。你试过吗?有什么错误吗? 是的,我试过了。我收到此错误错误在环境中找不到 ecs 任务定义(或空定义文件)。它抱怨找不到 dockerrun.aws.json。【参考方案2】:
    确保您的绑定地址正确(您打算使用的 IP 地址的主机名) 确保 JDBC 端口号正确 确保为相关端口打开安全组 当然,请验证数据库的用户名和密码

【讨论】:

我正在使用这个 spring.datasource.url=jdbc:mysql://db:3306/sbapi?allowPublicKeyRetrieval=true&useSSL=false,所以主机名是 dockerrun.aws.js 中的 db。用户名和密码也正确。 但我认为错误是无法连接MySQL。只是我不确定哪个配置出错了。 是有道理的,它消除了#1 和#2。你能确认是否有基本的连接 - 比如你能卷曲或 ping 你的数据库吗?很有可能是安全组(上面提到的#3)阻止了它 只是好奇,因为它在多个容器中,所以我还需要设置安全组吗? 我说的是数据库,我假设这是一个在 AWS 上运行的实例,它需要安全组 3306,允许其他 80 个。

以上是关于无法将多容器 docker 部署到 ElasticBeanstalk的主要内容,如果未能解决你的问题,请参考以下文章

将 Perl Docker 容器部署到 Elastic Beanstalk

无法访问 jarfile - Elastic Beanstalk 上的 Docker

在 Elastic Beanstalk 上部署 Docker 环境

如何将具有多个 Docker 容器的应用程序部署到 AWS Elastic Beanstalk?

Elastic Beanstalk 多容器 Docker 环境变量

使用 Docker 的开发环境并部署到 AWS Elastic Beanstalk