Docker Compose部署Spring Boot应用连接MySQL容器失败求助
Docker Compose部署Spring Boot+MySQL连接失败问题解决
问题描述
将开发的API打包为Docker镜像,尝试通过Docker Compose部署包含数据库在内的服务,但始终遭遇连接失败错误。调整数据库URL后,本地运行的API可成功连接容器化MySQL,但使用Docker Compose同时启动应用容器与MySQL容器时,应用无法连接数据库。
现有配置文件
docker-compose.yml
version: "2.4" services: trivia-quiz: image: omotoso/trivia-quiz-api ports: - "8080:8080" environment: SPRING_PROFILES_ACTIVE: PROD depends_on: - mysql mysql: image: mysql ports: - "3000:3306" environment: MYSQL_ROOT_PASSWORD: password MYSQL_DATABASE: db MYSQL_USER: my_user MYSQL_PASSWORD: password volumes: - mysql-data:/var/lib/mysql volumes: mysql-data:
app.yaml(Spring Boot配置)
spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver password: password url: jdbc:mysql://localhost:3000/db username: my_user jpa: hibernate: ddl-auto: update show-sql: false
错误信息
com.mysql.cj.jdbc.exceptions.CommunicationsException: 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 com.mysql.cj.jdbc.exceptions.SQLError.createCommunicationsException(SQLError.java:174) ~[mysql-connector-j-8.3.0.jar!/:8.3.0] at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:64) ~[mysql-connector-j-8.3.0.jar!/:8.3.0] at com.mysql.cj.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:815) ~[mysql-connector-j-8.3.0.jar!/:8.3.0] at com.mysql.cj.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:438) ~[mysql-connector-j-8.3.0.jar!/:8.3.0] at com.mysql.cj.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:241) ~[mysql-connector-j-8.3.0.jar!/:8.3.0] at com.mysql.cj.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:189) ~[mysql-connector-j-8.3.0.jar!/:8.3.0] at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:138) ~[HikariCP-5.0.1.jar!/:na] at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:359) ~[HikariCP-5.0.1.jar!/:na] at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:201) ~[HikariCP-5.0.1.jar!/:na] at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:470) ~[HikariCP-5.0.1.jar!/:na] at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:561) ~[HikariCP-5.0.1.jar!/:na] at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:100) ~[HikariCP-5.0.1.jar!/:na] at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:112) ~[HikariCP-5.0.1.jar!/:na]
解决方案
1. 修正数据库连接URL
Docker Compose默认会为服务创建内部网络,容器之间需通过服务名互相访问,而非localhost;同时容器内MySQL使用默认端口3306,不是映射到主机的3000。
修改app.yaml中的数据库URL:
spring: datasource: url: jdbc:mysql://mysql:3306/db?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
mysql是docker-compose中MySQL服务的名称,内部网络可直接解析- 添加
useSSL=false、allowPublicKeyRetrieval=true适配MySQL 8.x默认安全配置 serverTimezone=UTC避免时区不匹配导致的连接错误
2. 确保数据库就绪后再启动应用
depends_on仅保证启动顺序,不确保MySQL服务完全就绪。添加健康检查,让应用等待数据库可用后再启动:
更新docker-compose.yml:
version: "2.4" services: trivia-quiz: image: omotoso/trivia-quiz-api ports: - "8080:8080" environment: SPRING_PROFILES_ACTIVE: PROD depends_on: mysql: condition: service_healthy # 等待MySQL健康检查通过 mysql: image: mysql ports: - "3000:3306" environment: MYSQL_ROOT_PASSWORD: password MYSQL_DATABASE: db MYSQL_USER: my_user MYSQL_PASSWORD: password volumes: - mysql-data:/var/lib/mysql healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-ppassword"] interval: 5s # 每5秒检查一次 timeout: 5s # 超时时间5秒 retries: 5 # 重试5次后标记为不健康 volumes: mysql-data:
3. 用环境变量灵活覆盖配置(推荐)
避免硬编码配置,通过Docker环境变量覆盖Spring Boot参数,无需修改镜像内的配置文件:
更新docker-compose.yml的trivia-quiz服务:
trivia-quiz: image: omotoso/trivia-quiz-api ports: - "8080:8080" environment: SPRING_PROFILES_ACTIVE: PROD SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/db?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC SPRING_DATASOURCE_USERNAME: my_user SPRING_DATASOURCE_PASSWORD: password depends_on: mysql: condition: service_healthy
此方式配置更灵活,适配不同部署环境,无需修改镜像内的配置文件。
内容的提问来源于stack exchange,提问作者Omotoso Iyanu
相关产品推荐
相关产品推荐

