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

Docker Compose中PostgreSQL初始化异常,Spring应用连接失败求助

问题修复方案

核心问题根源

  1. 数据库容器共享存储卷冲突:两个PostgreSQL服务db-belt和db-crossbelt挂载了同一个pgdata卷,PostgreSQL会用该目录存储数据。第一个容器初始化完成后,第二个容器启动时检测到目录已有数据,会直接跳过初始化流程,导致crossbelt-microservices数据库未被创建。
  2. 应用启动时机不匹配:depends_on仅能保证数据库容器先启动,但PostgreSQL服务完全就绪需要一定时间,应用在数据库未准备好时发起连接必然失败。

具体修复步骤

1. 为每个数据库分配独立存储卷

修改docker-compose.yml,给两个数据库服务配置各自独立的存储卷,避免数据目录冲突:

services:
  belt-microservice:
    build: belt-microservices
    container_name: belt-microservice
    restart: always
    environment:
      - SPRING_DATASOURCE_URL=jdbc:postgresql://db-belt:5432/belt_microservices
    ports:
      - "8080:8080"
    depends_on:
      - db-belt
  crossbelt-microservice:
    build: crossbelt-microservices
    container_name: crossbelt-microservice
    restart: always
    environment:
      - SPRING_DATASOURCE_URL=jdbc:postgresql://db-crossbelt:5432/crossbelt_microservices
      - BELT_URL=http://belt-microservice:8080
    ports:
      - "8082:8082"
    depends_on:
      - db-crossbelt
      - belt-microservice
  report-microservice:
    build: report-microservices
    container_name: report-microservice
    restart: always
    ports:
      - "8083:8083"
  db-belt:
    image: postgres
    container_name: db-belt
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=password
      - POSTGRES_DB=belt-microservices
      - PGDATA=/var/lib/postgresql/data/pgdata
    ports:
      - "5000:5432"
    volumes:
      - pgdata-belt:/var/lib/postgresql/data
    restart: always
  db-crossbelt:
    image: postgres
    container_name: db-crossbelt
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=password
      - POSTGRES_DB=crossbelt-microservices
      - PGDATA=/var/lib/postgresql/data/pgdata
    ports:
      - "5001:5432"
    volumes:
      - pgdata-crossbelt:/var/lib/postgresql/data
    restart: always
volumes:
  pgdata-belt:
  pgdata-crossbelt:

2. 清理旧的共享存储卷(必须操作)

之前的pgdata卷已经存储了第一个数据库的数据,需要彻底删除才能让新容器正常初始化:

docker-compose down -v

3. 添加数据库就绪检测机制

方式一:Spring Boot内置重试配置

在每个微服务的application.yml中添加数据源重试配置,让应用自动重试数据库连接:

spring:
  datasource:
    driver-class-name: org.postgresql.Driver
    username: postgres
    password: password
    hikari:
      connection-timeout: 20000
      maximum-pool-size: 5
  jpa:
    hibernate:
      ddl-auto: update
  sql:
    init:
      mode: always

同时给项目添加Spring Retry依赖:
Maven(pom.xml):

<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

Gradle(build.gradle):

implementation 'org.springframework.retry:spring-retry'
implementation 'org.springframework.boot:spring-boot-starter-aop'

方式二:Docker Compose健康检查

修改数据库服务配置,添加健康检查,让应用仅在数据库完全就绪后启动:

db-belt:
  # 原有配置保留
  healthcheck:
    test: ["CMD-SHELL", "pg_isready -U postgres -d belt-microservices"]
    interval: 5s
    timeout: 5s
    retries: 5
db-crossbelt:
  # 原有配置保留
  healthcheck:
    test: ["CMD-SHELL", "pg_isready -U postgres -d crossbelt-microservices"]
    interval: 5s
    timeout: 5s
    retries: 5

然后更新应用服务的depends_on配置,依赖数据库的健康状态:

belt-microservice:
  # 原有配置保留
  depends_on:
    db-belt:
      condition: service_healthy
crossbelt-microservice:
  # 原有配置保留
  depends_on:
    db-crossbelt:
      condition: service_healthy
    belt-microservice:
      condition: service_started

4. 验证配置一致性

确认环境变量SPRING_DATASOURCE_URL中的数据库名称与POSTGRES_DB完全匹配:

  • db-belt的POSTGRES_DB为belt-microservices,对应应用URL为jdbc:postgresql://db-belt:5432/belt_microservices
  • db-crossbelt的POSTGRES_DB为crossbelt-microservices,对应应用URL为jdbc:postgresql://db-crossbelt:5432/crossbelt_microservices

启动验证

执行以下命令重新部署服务,检查日志确认数据库初始化和应用连接正常:

docker-compose up --build

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 06:44:51