Docker化Spring Boot与MySQL时JPA EntityManagerFactory初始化失败
Spring Boot + MySQL Docker容器化部署连接失败问题
本地运行正常的Spring Boot应用,在Docker容器化部署时出现数据库连接失败错误,具体错误日志如下:
org.hibernate.orm.deprecation : HHH90000025: MySQLDialect does not need to be specified explicitly using 'hibernate.dialect' (remove the property setting and it will be selected by default) db-1 | 2024-09-19T10:35:56.442175Z 0 [Warning] [MY-013746] [Server] A deprecated TLS version TLSv1 is enabled for channel mysql_main db-1 | 2024-09-19T10:35:56.442209Z 0 [Warning] [MY-013746] [Server] A deprecated TLS version TLSv1.1 is enabled for channel mysql_main db-1 | 2024-09-19T10:35:56.730732Z 6 [Warning] [MY-010453] [Server] root@localhost is created with an empty password ! Please consider switching off the --initialize-insecure option. app-1 | 2024-09-19T10:35:57.344Z INFO 1 --- [dockerFile] [ main] o.h.e.t.j.p.i.JtaPlatformInitiator : HHH000489: No JTA platform available (set 'hibernate.transaction.jta.platform' to enable JTA platform integration) app-1 | 2024-09-19T10:35:57.382Z INFO 1 --- [dockerFile] [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting... app-1 | 2024-09-19T10:35:58.513Z WARN 1 --- [dockerFile] [ main] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 0, SQLState: 08S01 app-1 | 2024-09-19T10:35:58.514Z ERROR 1 --- [dockerFile] [ main] o.h.engine.jdbc.spi.SqlExceptionHelper : ***Communications link failure app-1 | The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server. app-1 | 2024-09-19T10:35:58.523Z ERROR 1 --- [dockerFile] [ main] j.LocalContainerEntityManagerFactoryBean : Failed to initialize JPA EntityManagerFactory: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to open JDBC Connection for DDL execution [Communications link failure app-1 | The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.] [n/a] app-1 | 2024-09-19T10:35:58.524Z WARN 1 --- [dockerFile] [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to open JDBC Connection
当前配置文件
application.properties
spring.application.name=dockerFile spring.jpa.hibernate.ddl-auto=update spring.datasource.url=jdbc:mysql://localhost:3306/localspringbootdb?createDatabaseIfNotExist=true spring.datasource.username=root spring.datasource.password=use1234 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.jpa.properties.hibernate.boot.allow_jdbc_metadata_access=false spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect
Dockerfile
FROM openjdk:17-alpine WORKDIR /opt ENV PORT 8080 EXPOSE 8080 COPY target/*.jar /opt/app.jar ENTRYPOINT exec java $JAVA_OPTS -jar app.jar
docker-compose.yml
version: '2.29.4' services: app: image: javademo ports: - 8080:8080 environment: SPRING_DATASOURCE_URL: jdbc:mysql://db:3306/localspringbootdb SPRING_DATASOURCE_USERNAME: admin SPRING_DATASOURCE_PASSWORD: root depends_on: - db db: image: mysql:8.0.27 environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: localspringbootdb MYSQL_USER: admin MYSQL_PASSWORD: root ports: - 3307:3306
问题分析与修复方案
核心问题
- MySQL服务未就绪时Spring Boot已启动:
depends_on仅保证容器启动顺序,不确保MySQL服务完全可用,导致Spring Boot启动时无法建立连接。 - JDBC URL参数缺失:缺少时区、SSL、公钥检索等必要参数,适配MySQL 8.0时容易触发连接失败。
- 冗余配置警告:
hibernate.dialect无需手动指定,Hibernate会自动检测适配。
具体修复步骤
1. 配置MySQL健康检查与服务依赖
修改docker-compose.yml,添加MySQL健康检查,让Spring Boot等待MySQL服务完全就绪后再启动:
version: '3.8' # 修正无效版本号,使用支持健康检查的3.x版本 services: app: image: javademo ports: - 8080:8080 environment: SPRING_DATASOURCE_URL: jdbc:mysql://db:3306/localspringbootdb?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true SPRING_DATASOURCE_USERNAME: admin SPRING_DATASOURCE_PASSWORD: root SPRING_JPA_HIBERNATE_DDL_AUTO: update depends_on: db: condition: service_healthy # 等待MySQL健康检查通过 restart: on-failure # 连接失败时自动重启应用容器 db: image: mysql:8.0.27 environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: localspringbootdb MYSQL_USER: admin MYSQL_PASSWORD: root ports: - 3307:3306 healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "admin", "-proot"] interval: 5s timeout: 5s retries: 10
2. 优化JDBC URL参数
在application.properties中补充必要参数(docker-compose环境变量会覆盖本地配置,本地运行也兼容):
spring.application.name=dockerFile spring.jpa.hibernate.ddl-auto=update spring.datasource.url=jdbc:mysql://localhost:3306/localspringbootdb?createDatabaseIfNotExist=true&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true spring.datasource.username=root spring.datasource.password=use1234 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.jpa.properties.hibernate.boot.allow_jdbc_metadata_access=false # 移除冗余的方言配置,Hibernate自动适配 # spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect
3. 处理MySQL TLS警告(可选)
若要消除TLS版本警告,在docker-compose.yml的db服务中添加启动参数:
db: # ...其他配置 command: --tls-version=TLSv1.2
内容的提问来源于stack exchange,提问作者Kapil Kokcha
相关产品推荐
相关产品推荐

