使用Docker Compose部署Spring Boot+PostgreSQL遇JDBC连接错误求助
问题描述
部署Spring Boot+PostgreSQL项目(计划打标签推送至仓库后通过SSH在远程服务器部署)时,遇到Maven打包阶段的数据库连接问题:
application.properties中spring.datasource.url设为jdbc:postgresql://localhost/Arcade时,mvn clean package可正常执行,后续docker compose up --build也能正常启动容器- 将URL改为
jdbc:postgresql://arcade-db:5432/arcade(Docker Compose中数据库容器名)时,打包抛出JDBC连接异常 - 改为服务器IP:5432/arcade时,打包出现连接超时错误
- 尝试跳过Maven测试,仍提示数据库不可用
配置信息
application.properties
spring.application.name=Arcade spring.jpa.hibernate.ddl-auto = update spring.devtools.restart.enabled=true spring.resources.static-locations=classpath:/static/ spring.datasource.url = jdbc:postgresql://localhost/Arcade spring.datasource.username= *** spring.datasource.password= *** spring.datasource.driver-class-name=org.postgresql.Driver spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect spring.jpa.properties.hibernate.boot.allow_jdbc_metadata_access=false spring.sql.init.mode=never
docker-compose.yml
services: springapp: build: . container_name: arcade-springapp environment: SPRING_DATASOURCE_URL: jdbc:postgresql://arcade-db:5432/arcade ports: - 8000:8080 restart: always depends_on: - arcade-db networks: - backend arcade-db: image: postgres container_name: arcade-database environment: - POSTGRES_USER= *** - POSTGRES_PASSWORD= *** - POSTGRES_DB=arcade ports: - 5432:5432 volumes: - pgdata:/var/lib/postgresql/data restart: always networks: - backend volumes: pgdata: networks: backend:
Dockerfile
FROM openjdk:21 WORKDIR /app COPY /target/*.jar /app/app.jar EXPOSE 8080 CMD ["java", "-jar", "app.jar"]
错误现象
- URL改为
jdbc:postgresql://arcade-db:5432/arcade时,打包报错:
Caused by: org.hibernate.exception.JDBCConnectionException: Unable to open JDBC Connection for DDL execution [Connection failed] [n/a]
- URL改为服务器IP时,打包报错:
Caused by: java.net.SocketTimeoutException: Connect timed out
解决方案
1. 区分本地打包与容器运行的配置逻辑
不需要修改application.properties中的localhost配置——Docker Compose已经通过SPRING_DATASOURCE_URL环境变量覆盖了容器内的数据库连接地址。本地打包时用localhost是正确的(对应本地运行的PostgreSQL),容器启动时会自动切换为arcade-db:5432/arcade。
2. 本地打包时跳过数据库依赖操作
如果本地没有运行PostgreSQL,打包时需要跳过数据库相关的DDL执行和上下文初始化,执行以下命令:
mvn clean package -DskipTests -Dspring.jpa.hibernate.ddl-auto=none -Dspring.sql.init.mode=never
-DskipTests:跳过测试用例执行-Dspring.jpa.hibernate.ddl-auto=none:禁用Hibernate的DDL自动操作-Dspring.sql.init.mode=never:禁用Spring的数据库初始化脚本执行
3. 优化Docker多阶段构建(推荐)
使用多阶段Dockerfile,在Maven容器内完成打包,避免本地环境依赖,同时确保打包阶段不连接数据库:
# 构建阶段:Maven编译打包 FROM maven:3.9-eclipse-temurin-21 AS builder WORKDIR /app COPY pom.xml . COPY src ./src # 打包时跳过测试与数据库操作 RUN mvn clean package -DskipTests -Dspring.jpa.hibernate.ddl-auto=none -Dspring.sql.init.mode=never # 运行阶段:仅复制打包好的jar FROM openjdk:21 WORKDIR /app COPY --from=builder /app/target/*.jar app.jar EXPOSE 8080 CMD ["java", "-jar", "app.jar"]
执行docker compose up --build时,会自动完成构建与启动,无需本地执行mvn package。
4. 确保数据库容器就绪后再启动Spring应用
PostgreSQL容器启动后需要几秒才能接受连接,添加健康检查避免Spring应用启动时连接失败:
修改docker-compose.yml中arcade-db服务:
arcade-db: image: postgres container_name: arcade-database environment: - POSTGRES_USER= *** - POSTGRES_PASSWORD= *** - POSTGRES_DB=arcade ports: - 5432:5432 volumes: - pgdata:/var/lib/postgresql/data restart: always networks: - backend healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] interval: 5s timeout: 5s retries: 5
修改springapp服务的depends_on:
depends_on: arcade-db: condition: service_healthy
5. 其他部署方式参考
- 单服务器直接部署:在远程服务器安装JDK和PostgreSQL,上传Spring Boot jar包,通过环境变量指定数据库连接地址启动:
SPRING_DATASOURCE_URL=jdbc:postgresql://localhost:5432/arcade java -jar app.jar - Docker镜像仓库部署:将构建好的Spring Boot镜像推送到Docker Hub或私有仓库,远程服务器拉取镜像后配合Docker Compose启动。
内容的提问来源于stack exchange,提问作者Jonantha Willian
相关产品推荐
相关产品推荐

