Docker部署Spring Boot服务连接PostgreSQL遇连接拒绝问题
Docker容器中Spring Boot服务无法连接PostgreSQL的问题解决
问题场景
使用Docker Compose部署了运行在默认5432端口的PostgreSQL数据库容器,同时部署两个Spring Boot服务:
- user-service:宿主机8089端口映射到容器内8081端口
- order-service:宿主机8088端口映射到容器内8081端口
数据库与服务运行在不同容器中,本地通过命令行或IDE可正常连接数据库,但Docker中运行服务时出现连接拒绝错误:java.net.ConnectException: Connection refused。
数据库Docker Compose配置
version: "3.9" services: postgres: container_name: postgres_container image: postgres:16.3-alpine3.20 command: - "postgres" - "-c" - "max_connections=50" - "-c" - "shared_buffers=1GB" - "-c" - "effective_cache_size=4GB" - "-c" - "work_mem=16MB" - "-c" - "maintenance_work_mem=512MB" - "-c" - "random_page_cost=1.1" - "-c" - "temp_file_limit=10GB" - "-c" - "log_min_duration_statement=200ms" - "-c" - "idle_in_transaction_session_timeout=10s" - "-c" - "lock_timeout=1s" - "-c" - "statement_timeout=60s" - "-c" - "shared_preload_libraries=pg_stat_statements" - "-c" - "pg_stat_statements.max=10000" - "-c" - "pg_stat_statements.track=all" environment: POSTGRES_DB: "my_test_db" POSTGRES_USER: "username" POSTGRES_PASSWORD: "password" PGDATA: "/var/lib/postgresql/data/pgdata" volumes: - ./2. Init Database:/docker-entrypoint-initdb.d - my_test_db-data:/var/lib/postgresql/data - ./logs:/logs ports: - "5432:5432" healthcheck: test: ["CMD-SHELL","pg_isready -U username -d my_test_db"] interval: 10s timeout: 5s retries: 5 start_period: 10s restart: unless-stopped deploy: resources: limits: cpus: '1' memory: 4G networks: - postgres volumes: my_test_db-data: networks: postgres: driver: bridge
注:原配置中
pg_isready命令缺少空格,已修正为pg_isready -U username -d my_test_db
Spring Boot服务Docker Compose配置(原错误版本)
version: '3' services: user-service: container_name: user-service image: user-service build: context: usersMicro dockerfile: Dockerfile ports: - "8089:8081" environment: SPRING_DATASOURCE_URL: jdbc:postgresql://localhost:5432/my_test_db SPRING_DATASOURCE_USERNAME: username SPRING_DATASOURCE_PASSWORD: password order-service: container_name: order-service image: order-service build: context: orderMicro dockerfile: Dockerfile ports: - "8088:8081" environment: SPRING_DATASOURCE_URL: jdbc:postgresql://localhost:5432/my_test_db SPRING_DATASOURCE_USERNAME: username SPRING_DATASOURCE_PASSWORD: password networks: to_postgres: driver: postgres external: true
错误日志
user-service | Caused by: java.net.ConnectException: Connection refused user-service | at java.base/sun.nio.ch.Net.pollConnect(Native Method) ~[na:na] user-service | at java.base/sun.nio.ch.Net.pollConnectNow(Net.java:672) ~[na:na] user-service | at java.base/sun.nio.ch.NioSocketImpl.timedFinishConnect(NioSocketImpl.java:542) ~[na:na] user-service | at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:597) ~[na:na] user-service | at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:327) ~[na:na] user-service | at java.base/java.net.Socket.connect(Socket.java:633) ~[na:na] user-service | at org.postgresql.core.PGStream.createSocket(PGStream.java:243) ~[postgresql-42.7.3.jar!/:42.7.3] user-service | at org.postgresql.core.PGStream.<init>(PGStream.java:98) ~[postgresql-42.7.3.jar!/:42.7.3] user-service | at org.postgresql.core.v3.ConnectionFactoryImpl.tryConnect(ConnectionFactoryImpl.java:136) ~[postgresql-42.7.3.jar!/:42.7.3] user-service | at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:262) ~[postgresql-42.7.3.jar!/:42.7.3] user-service | ... 63 common frames omitted
问题分析
- 容器内localhost指向错误:Spring服务容器中的
localhost是容器自身,不是宿主机,因此无法通过localhost:5432访问PostgreSQL容器。 - 网络配置错误:Spring服务的Docker Compose中网络
driver设置为postgres是无效的,正确驱动应为bridge,且需关联到数据库所在的外部网络postgres。 - 服务启动顺序问题:Spring服务可能在PostgreSQL未完全就绪时就尝试连接,导致连接失败。
修复方案
1. 修改数据库连接地址
将Spring服务的SPRING_DATASOURCE_URL中的localhost替换为PostgreSQL容器的服务名postgres(Docker网络中可通过服务名直接解析容器IP)。
2. 修正网络配置
调整Spring服务的Docker Compose网络配置,使用正确的驱动并关联到数据库所在的外部网络。
3. 添加服务依赖与健康检查
给Spring服务添加depends_on配置,依赖PostgreSQL的健康状态,确保数据库就绪后再启动服务。
修改后的Spring Boot服务Docker Compose配置
version: '3' services: user-service: container_name: user-service image: user-service build: context: usersMicro dockerfile: Dockerfile ports: - "8089:8081" environment: SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/my_test_db SPRING_DATASOURCE_USERNAME: username SPRING_DATASOURCE_PASSWORD: password depends_on: postgres: condition: service_healthy order-service: container_name: order-service image: order-service build: context: orderMicro dockerfile: Dockerfile ports: - "8088:8081" environment: SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/my_test_db SPRING_DATASOURCE_USERNAME: username SPRING_DATASOURCE_PASSWORD: password depends_on: postgres: condition: service_healthy networks: postgres: external: true
额外说明
- 确保PostgreSQL容器的网络
postgres已创建(执行docker network ls可查看,若不存在可通过docker-compose up -d启动数据库容器自动创建)。 - 若使用Docker Desktop,也可通过
host.docker.internal代替localhost访问宿主机,但推荐使用Docker服务名的方式,更符合容器化架构设计。
内容的提问来源于stack exchange,提问作者Артём Орёл
相关产品推荐
相关产品推荐

