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

Spring Boot+Docker部署Postgres遇连接超时及容器自动关闭问题

Spring Boot Docker Compose 启停异常排查

环境与配置

  • 系统:Ubuntu
  • Spring Boot版本:3.3.0
  • Docker版本:26.1.3 (build b72abbb)
  • 使用spring-boot-docker-compose实现启动时自动拉起Docker镜像

核心配置文件

pom.xml

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-docker-compose</artifactId>
    <scope>runtime</scope>
    <optional>true</optional>
</dependency>

Dockerfile

# Use the Amazon Corretto 21 base image
FROM amazoncorretto:21.0.3

# Create a volume for temporary files
VOLUME /tmp

# Arguments for the JAR file to be copied
ARG JAR_FILE=target/*.jar

EXPOSE 8080
EXPOSE 5432

# Copy the JAR file into the Docker image
COPY ${JAR_FILE} /app.jar

# Set the entry point for the container to run the application
ENTRYPOINT ["java","-jar","/app.jar"]

docker-compose.yml

version: '3.8'
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "8081:8080"
    environment:
      SPRING_PROFILES_ACTIVE: dev
    network_mode: host
  postgres:
    image: postgres:latest
    restart: on-failure
    environment:
      - POSTGRES_DB=expiry_service_db
      - POSTGRES_PASSWORD=postgres
      - POSTGRES_USER=postgres
    ports:
      - "5431:5432"
    network_mode: host

application.properties

spring.application.name=expiry-service
server.port=8080
# expiry_service datasource
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/expiry_service_db
spring.datasource.username=postgres
spring.datasource.password=postgres
#spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.database-platform=postgres
spring.jpa.hibernate.ddl-auto=update

问题现象

启动Spring Boot应用后,Tomcat在8080端口启动,Docker Desktop显示app和postgres容器已运行,但等待约2分钟后,两个容器均停止。

容器日志

postgres-1  | 2024-06-07 12:05:29.558 UTC [1] LOG:  received fast shutdown request
postgres-1  | 2024-06-07 12:05:29.566 UTC [39] FATAL:  terminating connection due to administrator command
postgres-1  | 2024-06-07 12:05:29.566 UTC [1] LOG:  background worker "logical replication launcher" (PID 32) exited with exit code 1
postgres-1  | 2024-06-07 12:05:29.569 UTC [27] LOG:  shutting down
postgres-1  | 2024-06-07 12:05:29.572 UTC [27] LOG:  checkpoint starting: shutdown immediate
app-1       | 2024-06-07T12:05:29.576Z  INFO 1 --- [expiry-service] [ionShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
postgres-1  | 2024-06-07 12:05:29.600 UTC [1] LOG:  database system is shut down
postgres-1 exited with code 0

Spring Boot日志

org.springframework.boot.docker.compose.lifecycle.ReadinessTimeoutException: Readiness timeout of PT2M reached while waiting for services [expiry-service-app-1]
    at org.springframework.boot.docker.compose.lifecycle.ServiceReadinessChecks.waitUntilReady(ServiceReadinessChecks.java:83) ~[spring-boot-docker-compose-3.3.0.jar:3.3.0]

Suppressed: org.springframework.boot.docker.compose.lifecycle.ServiceNotReadyException: IOException while connecting to port 8080

    Caused by: java.net.ConnectException: Connection refused

问题解答

1. 能否通过POSTGRES_DB参数自动创建数据库?

可以。Postgres官方镜像原生支持通过POSTGRES_DB、POSTGRES_USER、POSTGRES_PASSWORD三个参数的组合,在容器首次启动时自动创建指定名称的数据库,并将该数据库设为POSTGRES_USER的默认数据库。你当前的docker-compose.yml已完整配置这三个参数,所以expiry_service_db应该会被自动创建,这个环节不存在问题。

2. 数据库为何自动关闭?

容器自动关闭的核心原因是Spring Boot Docker Compose的就绪检查超时,触发了所有关联容器的自动停止,而就绪检查失败的根源是应用服务(app)未能正常启动并监听8080端口,具体问题出在以下配置冲突:

  • network_mode: host导致的端口与网络问题
    host模式下容器直接复用主机网络栈,ports配置会被忽略:

    • 对于postgres:你配置的5431:5432端口映射无效,容器会直接占用主机的5432端口。如果主机5432端口被其他进程占用,postgres启动会失败;即使启动成功,若postgres启动速度慢于应用,应用会因无法连接数据库而启动失败。
    • 对于app:容器的8080端口直接使用主机8080端口,若主机该端口已被占用,应用无法启动,导致Spring Boot Docker Compose的就绪检查(默认监听8080端口)无法连接,触发2分钟超时后关闭所有容器。
  • 缺少服务依赖与健康检查
    未配置app服务等待postgres就绪的逻辑,应用会在postgres完全启动前尝试连接,导致连接失败进而启动失败,端口无法监听,最终触发就绪检查超时。

修复建议

  1. 移除network_mode: host
    使用Docker默认桥接网络,服务间可通过服务名(如postgres)访问,同时修改application.properties的数据库URL:

    spring.datasource.url=jdbc:postgresql://postgres:5432/expiry_service_db
    
  2. 配置服务依赖与健康检查
    在docker-compose.yml中添加依赖关系与postgres健康检查,确保postgres就绪后再启动app:

    version: '3.8'
    services:
      app:
        build:
          context: .
          dockerfile: Dockerfile
        ports:
          - "8081:8080"
        environment:
          SPRING_PROFILES_ACTIVE: dev
        depends_on:
          postgres:
            condition: service_healthy
      postgres:
        image: postgres:latest
        restart: on-failure
        environment:
          - POSTGRES_DB=expiry_service_db
          - POSTGRES_PASSWORD=postgres
          - POSTGRES_USER=postgres
        ports:
          - "5431:5432"
        healthcheck:
          test: ["CMD-SHELL", "pg_isready -U postgres -d expiry_service_db"]
          interval: 5s
          timeout: 5s
          retries: 5
    
  3. 调整数据库连接超时配置
    在application.properties中增加连接池超时设置,给数据库足够的启动时间:

    spring.datasource.hikari.connection-timeout=30000
    spring.datasource.hikari.maximum-pool-size=10
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 16:30:08