使用 docker-compose 在 Docker 容器中运行时,尝试将 Spring Boot 应用程序连接到 MySQL 时,通信链路失败

问题描述 投票:0回答:1

我的目标是连接两个 docker 容器:一个是一个简单的微服务,一个 Spring Boot 应用程序,另一个是在 Windows 10 本地计算机的 docker 容器中运行的简单 MySQL 数据库。在花了大约 16 个小时尝试连接我的 Spring Boot 后应用程序并尽可能阅读它,并在 StackeOverflow、互联网其他地方和 ChatGTP 中寻找解决方案,我仍然找不到如何连接到另一个容器中的数据库的解决方案。我看到人们问这个问题,当我尝试帮助他们的答案时,它对我不起作用。我一直遇到同样的问题:

com.mysql.cj.jdbc.exceptions.CommunicationsException: Communications link failure

我有 docker-compose.yaml:

version: '3.7'

    services:
      docker-mysql:
        image: mysql:latest
        ports:
          - "3307:3306"
        environment:
          MYSQL_DATABASE: wallet_microservice
          MYSQL_ROOT_PASSWORD: root
          SPRING_DATASOURCE_USERNAME: root
          SPRING_DATASOURCE_PASSWORD: root
    
        volumes:
          - ./src/main/resources/data/schema.sql:/docker-entrypoint-initdb.d/schema.sql
      myapp:
        build:
          dockerfile: Dockerfile
        ports:
          - "8080:8080"
    
        environment:
          SPRING_DATASOURCE_URL: jdbc:mysql://docker-mysql:3306/wallet_microservice?autoReconnect=true&useSSL=false
    
        depends_on:
          - docker-mysql

Dockerfile:

FROM eclipse-temurin:17
WORKDIR /app
COPY build/libs/*.jar app.jar
CMD ["java", "-jar", "app.jar"]

Spring boot应用程序中的application.properties:

spring.datasource.url=jdbc:mysql://docker-mysql:3306/wallet_microservice
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect

如果我在与 docker 相同的机器上的 localhost 中运行该应用程序,那么我可以从同一个 Spring boot 应用程序成功连接到此容器中运行的数据库,然后我只需将应用程序的 application.properties 中的数据源行更改为

spring.datasource.url=jdbc:mysql://localhost:3307/wallet_microservice

当我向 ChatGTP 咨询故障排除时,我得到反馈:(所有事情似乎都很好) 网络配置:

  1. docker-compose.yml 文件没有显式定义自定义网络,因此 Docker Compose 将为服务创建默认网络。由于 myapp 和 docker-mysql 都定义在同一个 docker-compose.yml 文件中,因此默认情况下它们应该位于同一网络中。
  2. Docker 服务依赖: Docker Compose的depends_on仅确保服务按照指定的顺序启动。它不保证服务已完全初始化并准备好接受连接。因此,myapp 有可能在 docker-mysql 完全初始化之前启动。为了解决这个问题,您可能需要在 myapp 中实现重试机制,以等待 MySQL 服务准备好接受连接。 // 这里是我的评论:我尝试使用 Postman 手动连接,仍然是相同的连接错误,所以时间似乎不是原因。
  3. MySQL配置: 提供的 Docker Compose 配置使用必要的环境变量(MYSQL_DATABASE、MYSQL_ROOT_PASSWORD 等)设置 MySQL 容器。这个设置看起来是正确的。
  4. 防火墙或安全设置: 由于 myapp 和 docker-mysql 都在同一主机上的 Docker 容器中运行,因此主机内的防火墙或安全设置不太可能是问题的原因。但是,仍然值得检查是否有任何可能干扰的本地防火墙规则。
  5. Docker Compose 配置: docker-compose.yml 文件似乎已正确配置了必要的服务定义和端口映射。 MySQL 的端口映射 (3307:3306) 确保主机上的端口 3307 映射到 MySQL 正在侦听的 Docker 容器中的端口 3306。
mysql spring-boot docker docker-compose
1个回答
0
投票

我怀疑这是因为您的应用程序在完全初始化之前尝试连接到数据库。

version: '3.7'

services:
  docker-mysql:
    image: mysql:latest
    container_name: mysql
    environment:
      MYSQL_ROOT_PASSWORD: root
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
      interval: 5s
      timeout: 5s
      retries: 5
  myapp:
    image: mysql:latest
    container_name: myapp
    depends_on:
      docker-mysql:
        condition: service_healthy
    command: mysql -h docker-mysql -u root -p'root' -e 'SHOW DATABASES;'

您需要使用

depends_on
,但这还不足以检查数据库服务是否已启动。您需要确保实际数据库已初始化并准备好接受连接。

因此,为数据库服务创建一个

healthcheck
,只有当您能够 ping 数据库时,该服务才会通过。然后让您的应用程序等待服务被标记为“健康”。

docker-compose.yml
中,我已将您的应用程序替换为一个容器,该容器仅连接到数据库并执行简单的 SQL 查询。这将表明数据库服务已准备就绪。

您可以修改“interval

, 
timeout
and
retries”的值,但提供的值是一个合理的起点。

© www.soinside.com 2019 - 2024. All rights reserved.