Docker-Compose环境下Spring Boot无法连接PostgreSQL数据库
问题背景
在VPS上使用docker-compose部署PostgreSQL数据库和Spring Boot API服务栈,两者处于同一Docker网络。本地环境下,单独运行的API(非容器化)可通过主机暴露的端口正常连接容器内的数据库,但生产环境的docker-compose部署出现错误:
java.lang.IllegalArgumentException: URL must start with 'jdbc'
排查与解决方法
1. 验证API容器的环境变量是否正确传递
进入API容器查看环境变量,确认DATABASE_NAME、DATABASE_USER等变量是否存在且值正确:
docker exec -it <你的API容器名称或ID> env
- 如果变量缺失或值错误,检查启动命令中的变量拼写是否正确,或docker-compose中环境变量的定义是否有误。
- 可以在docker-compose的
api服务环境变量中添加强制非空检查,避免空值传递:environment: - SPRING_PROFILES_ACTIVE=${SPRING_PROFILES_ACTIVE:?必须指定SPRING_PROFILES_ACTIVE} - DATABASE_NAME=${DATABASE_NAME:?必须指定DATABASE_NAME} - DATABASE_USER=${DATABASE_USER:?必须指定DATABASE_USER} - DATABASE_PASSWORD=${DATABASE_PASSWORD:?必须指定DATABASE_PASSWORD}
2. 检查prod环境的配置文件覆盖情况
由于启动时指定了SPRING_PROFILES_ACTIVE=prod,需确认:
- 是否存在
application-prod.properties文件; - 该文件中是否覆盖了
spring.datasource.url,是否出现拼写错误(比如遗漏jdbc:前缀)或空值。
3. 确认API容器内的配置文件内容
进入API容器查看实际加载的application.properties内容,检查spring.datasource.url的定义是否正确:
docker exec -it <你的API容器名称或ID> cat /<容器内配置文件路径>/application.properties
(注:容器内路径通常为/app/application.properties或/opt/app/application.properties,根据你的Spring Boot镜像调整)
4. 修正数据库就绪检查逻辑
depends_on仅保证容器启动顺序,不确保数据库服务已就绪。为API服务添加健康检查依赖,确保数据库就绪后再启动API:
修改docker-compose的db服务:
services: db: image: postgres ports: - ${DATABASE_PORT}:5432 environment: - POSTGRES_USER=${DATABASE_USER} - POSTGRES_PASSWORD=${DATABASE_PASSWORD} - POSTGRES_DB=${DATABASE_NAME} healthcheck: test: ["CMD-SHELL", "pg_isready -U ${DATABASE_USER} -d ${DATABASE_NAME}"] interval: 5s timeout: 5s retries: 5 api: # ... 其他配置 depends_on: db: condition: service_healthy
5. 检查Spring Boot配置加载优先级
Spring Boot的配置优先级中,环境变量高于配置文件。检查API容器中是否存在SPRING_DATASOURCE_URL环境变量,若该变量为空或格式错误,会覆盖配置文件中的URL:
docker exec -it <你的API容器名称或ID> env | grep SPRING_DATASOURCE
如果存在错误的SPRING_DATASOURCE_URL,需排查是否在启动命令或docker-compose中误设置了该变量。
6. 测试容器间网络连通性
在API容器内测试与数据库容器的网络连通性,确认网络是否正常:
docker exec -it <你的API容器名称或ID> ping db
若ping不通,检查docker-compose的网络配置,确保api和db服务都加入了app-network(当前配置已指定,但可确认容器实际所属网络:docker inspect <容器ID> | grep Networks)
内容的提问来源于stack exchange,提问作者Johni

