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

Docker Compose depends_on条件失效:Spring Boot API与MS SQL Server启动问题

我之前搭建Spring Boot + MS SQL的Docker环境时,也碰到过一模一样的问题——API总是抢在数据库初始化完成前启动,导致连接失败。给你几个亲测有效的解决方向:

解决思路与方案

1. 先修复健康检查的核心问题

你当前的健康检查有个致命漏洞:MS SQL容器里设置的SA_PASSWORD是<my pw>,但健康检查命令里硬编码的却是CorrectHorseBatteryStapleFor$,密码不匹配导致健康检查永远失败,service_healthy条件自然不会生效。

先把密码统一,再调整健康检查逻辑,确保它能准确判断数据库完全初始化完成(不仅是SQL Server启动,还要你的初始化脚本执行完毕):

HEALTHCHECK --interval=10s --timeout=10s --start-period=60s --retries=10 CMD /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P "$SA_PASSWORD" -d dwh-demo -Q "SELECT 1" > /dev/null 2>&1 || exit 1
  • 用$SA_PASSWORD引用环境变量,避免硬编码密码不一致
  • 把start-period设为60s,给初始化脚本足够的执行时间
  • 重定向输出到/dev/null,减少不必要的日志噪音

2. 别再用service_completed_successfully(用错场景了)

service_completed_successfully是用来等待一次性任务容器执行完毕退出的(比如临时数据迁移容器),但你的MS SQL是长期运行的服务容器,这个条件永远不会满足,所以API会直接启动——这就是为什么这个配置完全没用。你必须用service_healthy,但前提是健康检查配置正确。

3. 在Spring Boot里添加连接重试(最可靠的兜底方案)

Docker的健康检查偶尔会有延迟或误判,最好在应用层面也做连接重试,确保启动时能等待数据库就绪。在application.properties(或yaml)里配置Hikari连接池参数:

# HikariCP连接池配置
spring.datasource.hikari.connection-timeout=60000
spring.datasource.hikari.validation-timeout=5000
spring.datasource.hikari.maximum-pool-size=10
spring.datasource.hikari.connection-test-query=SELECT 1
spring.datasource.hikari.initialization-fail-timeout=0
  • initialization-fail-timeout=0表示连接池会一直重试,直到成功连接数据库
  • connection-timeout设为60秒,给足够的重试缓冲时间

另外,还可以用Spring Boot的@Retryable注解重试数据库初始化操作:

@Configuration
@EnableRetry
public class RetryConfig {
}

@Service
public class DatabaseInitService {
    @Retryable(value = {SQLException.class}, maxAttempts = 10, backoff = @Backoff(delay = 2000))
    public void initDatabase() {
        // 执行需要数据库就绪的初始化逻辑
    }
}

4. 用等待脚本让API启动前先等数据库

如果不想依赖Docker的健康检查,可以在API容器里加入wait-for-it.sh脚本,强制API启动前先检查数据库的连通性:

  1. 把wait-for-it.sh下载到你的API项目目录,或者在Dockerfile里直接下载:
    RUN wget https://raw.githubusercontent.com/vishnubob/wait-for-it/master/wait-for-it.sh -O wait-for-it.sh && chmod +x wait-for-it.sh
    
  2. 修改API的Dockerfile的CMD:
    CMD ["./wait-for-it.sh", "db:1433", "--", "mvn", "spring-boot:run"]
    

这个脚本会一直等待db容器的1433端口能连通,才会启动Spring Boot应用。

5. 优化数据库初始化脚本的执行顺序

确保你的初始化脚本执行完成后,SQL Server才会被标记为健康。可以在entrypoint.sh里先等待SQL Server启动,再执行初始化脚本:

# entrypoint.sh内容
# 等待SQL Server启动就绪
until /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P "$SA_PASSWORD" -Q "SELECT 1" > /dev/null 2>&1; do
    echo "等待SQL Server启动中..."
    sleep 5
done

# 执行初始化脚本
/opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P "$SA_PASSWORD" -i init.sql

# 保持容器运行
tail -f /dev/null

这样初始化脚本只有在SQL Server完全启动后才会执行,完成后容器才能进入健康状态。

内容的提问来源于stack exchange,提问作者Playing With BI

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 16:56:14