使用Docker Compose运行Spring Boot应用时出现PostgreSQL连接拒绝错误
核心问题分析
你遇到的PostgreSQL连接拒绝问题,主要集中在跨Docker Compose文件的网络共享、服务启动顺序依赖、PostgreSQL监听配置这几个关键节点,以下是针对性的解决方案:
1. 确保两个Compose使用同一外部网络
当使用独立的Docker Compose文件时,直接在每个文件里定义mynetwork会导致Docker自动创建两个不同的网络(命名规则为当前目录名_mynetwork),无法实现容器间的网络共享。
解决步骤:
- 先手动创建外部网络:
docker network create mynetwork - 修改PostgreSQL的docker-compose.yml,将网络声明为外部网络:
version: '2' services: database: image: postgis/postgis container_name: postgresql networks: - mynetwork environment: - POSTGRES_USER=admin - POSTGRES_PASSWORD=admin - POSTGRES_DB=mydb ports: - "5432:5432" volumes: - "./datadb:/var/lib/postgresql/data" networks: mynetwork: external: true # 标记为已手动创建的外部网络 - 修改Spring Boot的docker-compose.yml,同样设置网络为外部:
version: '2' services: backend: build: . container_name: spring-application ports: - 8085:8085 networks: - mynetwork environment: - SPRING_DATASOURCE_URL=jdbc:postgresql://postgresql:5432/mydb - SPRING_DATASOURCE_USERNAME=admin - SPRING_DATASOURCE_PASSWORD=admin - SPRING_JPA_HIBERNATE_DDL_AUTO=update networks: mynetwork: external: true
2. 修复跨Compose的启动依赖问题
depends_on仅在同一个Docker Compose文件内生效,跨文件时这个配置不会等待PostgreSQL容器完全就绪。你需要添加启动等待逻辑:
方案1:在Spring Boot启动脚本中添加等待逻辑
修改Dockerfile,在启动命令前加入检测PostgreSQL端口就绪的逻辑:
FROM openjdk:17-jdk-slim WORKDIR /app COPY target/your-app.jar app.jar # 安装curl用于端口检测 RUN apt-get update && apt-get install -y curl # 等待postgresql:5432端口就绪后启动应用 CMD ["bash", "-c", "until curl -s postgresql:5432 > /dev/null; do sleep 2; done; java -jar app.jar"]
方案2:使用Docker Compose健康检查(推荐)
在PostgreSQL的docker-compose.yml中添加健康检查,确保Spring Boot只在数据库就绪后启动:
services: database: image: postgis/postgis container_name: postgresql networks: - mynetwork environment: - POSTGRES_USER=admin - POSTGRES_PASSWORD=admin - POSTGRES_DB=mydb ports: - "5432:5432" volumes: - "./datadb:/var/lib/postgresql/data" healthcheck: test: ["CMD-SHELL", "pg_isready -U admin -d mydb"] interval: 5s timeout: 5s retries: 5
然后在Spring Boot的docker-compose.yml中,修改depends_on依赖数据库的健康状态:
services: backend: build: . container_name: spring-application ports: - 8085:8085 networks: - mynetwork environment: - SPRING_DATASOURCE_URL=jdbc:postgresql://postgresql:5432/mydb - SPRING_DATASOURCE_USERNAME=admin - SPRING_DATASOURCE_PASSWORD=admin - SPRING_JPA_HIBERNATE_DDL_AUTO=update depends_on: database: condition: service_healthy # 等待数据库健康检查通过
3. 确认PostgreSQL的监听配置
即使修改了pg_hba.conf,如果postgresql.conf中的listen_addresses设置为localhost,PostgreSQL只会监听容器内部的localhost,拒绝外部容器的连接。
解决方法:
- 进入PostgreSQL容器:
docker exec -it postgresql bash - 编辑
postgresql.conf(路径通常为/var/lib/postgresql/data/postgresql.conf):vi /var/lib/postgresql/data/postgresql.conf - 修改监听地址:
listen_addresses = '*' - 重启PostgreSQL容器:
docker restart postgresql
或者直接通过Docker环境变量设置(部分PostgreSQL镜像支持),在PostgreSQL的docker-compose.yml中添加:
environment: - POSTGRES_USER=admin - POSTGRES_PASSWORD=admin - POSTGRES_DB=mydb - POSTGRES_LISTEN_ADDRESSES='*' # 添加该环境变量
4. 验证网络连通性
如果以上步骤完成后仍有问题,先验证Spring Boot容器能否访问PostgreSQL容器:
- 进入Spring Boot容器:
docker exec -it spring-application bash - 执行ping命令检测主机名解析:
ping postgresql
如果ping不通,说明网络未正确共享,检查网络创建和compose配置;如果ping通但连接失败,检查端口监听状态:
telnet postgresql 5432
内容的提问来源于stack exchange,提问作者HindB

