You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何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可连接后再启动应用。步骤如下:

  1. 创建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
  1. 修改Dockerfile,复制脚本并设置执行权限:
FROM openjdk:17

COPY target/crudapp.jar .
COPY start.sh .
RUN chmod +x start.sh

EXPOSE 8080

ENTRYPOINT ["./start.sh"]

内容的提问来源于stack exchange,提问作者SSSsa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 17:55:16