为何Docker Compose部署Spring Boot+MySQL首次运行失败,二次运行正常?
Spring Boot + Docker Compose 首次启动失败、二次启动正常的原因及解决方法
核心原因
你的推测完全正确:Docker Compose的depends_on仅保证容器的启动顺序,不会等待数据库内部服务完全就绪。首次运行时,MySQL容器虽然启动了,但初始化流程(创建指定数据库、加载配置、启动TCP监听)还没完成,此时Spring Boot应用尝试建立数据库连接就会失败。第二次运行时,MySQL容器要么已经完成初始化,要么通过持久化卷直接恢复了就绪状态,所以应用能正常连接。
另外注意:你的docker-compose.yml里写的version: '5'是错误的,Docker Compose目前没有这个版本,建议改为3.8(主流稳定版本),避免出现兼容性问题。
解决方案
方案1:给Spring Boot配置连接重试机制
通过Hikari连接池的参数,让应用在数据库未就绪时自动重试连接,无需修改容器启动逻辑。可以直接在application.properties或Docker Compose的环境变量中添加:
# Hikari连接池配置 spring.datasource.hikari.connection-timeout=30000 spring.datasource.hikari.initialization-fail-timeout=0 # 无限等待直到连接成功 spring.datasource.hikari.maximum-pool-size=10 # 连接有效性校验 spring.datasource.test-on-borrow=true spring.datasource.validation-query=SELECT 1 spring.datasource.validation-interval=30000
如果用Docker Compose环境变量传递,对应写法是:
environment: # ... 其他变量 SPRING_DATASOURCE_HIKARI_CONNECTION-TIMEOUT: 30000 SPRING_DATASOURCE_HIKARI_INITIALIZATION-FAIL-TIMEOUT: 0 SPRING_DATASOURCE-TEST-ON-BORROW: true SPRING_DATASOURCE-VALIDATION-QUERY: "SELECT 1"
方案2:用Docker Compose健康检查实现条件启动
给MySQL服务添加健康检查规则,让Spring Boot应用只有在MySQL服务真正就绪后才启动。修改后的docker-compose.yml如下:
version: '3.8' services: mysql: image: mysql:latest ports: - "3307:3306" environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: rentalapp command: mysqld --sql_mode="" volumes: - ./my.cnf:/etc/mysql/my.cnf container_name: mysqlimage1 healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-proot"] interval: 5s # 每5秒检查一次 timeout: 5s # 超时时间5秒 retries: 10 # 最多重试10次 app: image: crudimage:crudapp ports: - "8090:8080" environment: SPRING_JPA_GENERATE_DDL: true SPRING_JPA_HIBERNATE_DDL_AUTO: update SPRING_JPA_DATABASE_PLATFORM: org.hibernate.dialect.MySQLDialect SPRING_JPA_SHOW_SQL: true SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/rentalapp SPRING_DATASOURCE_USERNAME: root SPRING_DATASOURCE_PASSWORD: root SERVER_ERROR_INCLUDE_MESSAGE: always depends_on: mysql: condition: service_healthy # 等待MySQL健康检查通过 container_name: crudappimage1
方案3:自定义启动脚本(可选)
给Spring Boot应用添加一个启动前的检查脚本,确认MySQL可连接后再启动应用。步骤如下:
- 创建
start.sh脚本:
#!/bin/bash # 循环检查MySQL连接,直到成功 until mysql -h mysql -u root -proot -e "SELECT 1"; do echo "等待MySQL服务启动..." sleep 2 done # 启动Spring Boot应用 java -jar crudapp.jar
- 修改Dockerfile,复制脚本并设置执行权限:
FROM openjdk:17 COPY target/crudapp.jar . COPY start.sh . RUN chmod +x start.sh EXPOSE 8080 ENTRYPOINT ["./start.sh"]
内容的提问来源于stack exchange,提问作者SSSsa
相关产品推荐
相关产品推荐

