无效 JDBC-Url: Driver org.postgresql.Driver claims to not accept jdbcUrl, jdbc:postgresql://${DB_ADDR_ALIAS}:${DB_PORT}/${DB_NAME}

Invalid JDBC-Url: Driver org.postgresql.Driver claims to not accept jdbcUrl, jdbc:postgresql://${DB_ADDR_ALIAS}:${DB_PORT}/${DB_NAME}

起始情况: 我正在使用 Spring Boot 和 Maven 构建 REST 服务。此 REST 服务正在写入 Postgres 数据库。两个组件都通过以下docker-compose.ymldocker化和配置(我使用.env文件隔离机密和重复信息。${DB_Name} 计算为“Taskitory”。):

version: "0.0.1"
services:
  db:
    container_name: taskitory-db
    image: postgres:14.1
    environment:
      - POSTGRES_DB=${DB_NAME}
      - POSTGRES_USER=${DB_ADMIN_USER}
      - POSTGRES_PASSWORD=${DB_ADMIN_PW}
      - PGDATA=/data/postgres
    volumes:
      - ./postgres-volume:/data
    networks:
      - taskitory-net
    ports:
      - "60000:5432"
    restart: unless-stopped
  backend:
    container_name: taskitory-backend
    build: .
    networks:
      - taskitory-net
    ports:
      - "80:8080"
    depends_on:
      - db
networks:
  taskitory-net:
    driver: bridge

由于我使用 Spring Boot with Maven 和 Java 作为我的 REST 服务,我使用 JPA 和 Hibernate 来写入我的数据库。用于访问数据库的配置位于我的 Spring 引导项目的 application.properties 中:

server.port                             = 8080

logging.level.jdbc                      = OFF
logging.level.jdbc.sqltiming            = DEBUG
logging.level.jdbc.resultsettable       = DEBUG

spring.datasource.driver-class-name     = org.postgresql.Driver
spring.datasource.url                   = jdbc:postgresql://${DB_ADDR_ALIAS}:${DB_PORT}/${DB_NAME}
spring.datasource.username              = ${DB_CLIENT_USER}
spring.datasource.password              = ${DB_CLIENT_PW}
spring.datasource.hikari.max-lifetime   = 600000
spring.datasource.testWhileIdle         = true
spring.datasource.test-on-borrow        = true
spring.datasource.hikari.schema         = backend
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto           = validate

我也在 application.properties 中使用 .env 文件中的变量。因此 spring.datasource.url 从 "jdbc:postgresql://${DB_ADDR_ALIAS}:${DB_PORT}/${DB_NAME }”到“jdbc:postgresql://db:5432/Taskitory”,使用 .env 文件中的以下代码:

DB_ADDR_ALIAS="db"
DB_PORT="5432"
DB_NAME="Taskitory"
DB_BE_SCHEMA="backend"

问题描述: 为了让我的 Spring 启动应用程序连接到数据库,我将 jdbc-url 的主机设置为我的数据库容器的服务名称(“db") 在我的 docker-compose.yml 中指定。此外,我将 jdbc-url 的端口设置为 postgres 的本机端口“5432”。这样,DB 容器应该可以从 Spring 引导容器通过两个容器都连接到的 docker-网络“taskitory-net”访问。当我尝试构建我的 Spring 引导应用程序时,出现以下错误(我需要缩短错误消息以免超出字符限制):

#10 30.45 Caused by: java.lang.RuntimeException: Driver org.postgresql.Driver claims to not accept jdbcUrl, jdbc:postgresql://${DB_ADDR_ALIAS}:${DB_PORT}/${DB_NAME}
#10 30.45       at com.zaxxer.hikari.util.DriverDataSource.<init>(DriverDataSource.java:110) ~[HikariCP-4.0.3.jar:na]
#10 30.45       at com.zaxxer.hikari.pool.PoolBase.initializeDataSource(PoolBase.java:331) ~[HikariCP-4.0.3.jar:na]
#10 30.45       at com.zaxxer.hikari.pool.PoolBase.<init>(PoolBase.java:114) ~[HikariCP-4.0.3.jar:na]
#10 30.45       at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:108) ~[HikariCP-4.0.3.jar:na]
#10 30.45       at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:112) ~[HikariCP-4.0.3.jar:na]
#10 30.45       at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final]
#10 30.45       at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:181) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final]
#10 30.45       at org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl.getIsolatedConnection(DdlTransactionIsolatorNonJtaImpl.java:44) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final]
#10 30.45       at org.hibernate.tool.schema.internal.exec.ImprovedExtractionContextImpl.getJdbcConnection(ImprovedExtractionContextImpl.java:63) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final]
#10 30.45       at org.hibernate.tool.schema.extract.spi.ExtractionContext.getQueryResults(ExtractionContext.java:43) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final]
#10 30.45       at org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl.extractMetadata(SequenceInformationExtractorLegacyImpl.java:39) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final]
#10 30.45       at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.initializeSequences(DatabaseInformationImpl.java:66) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final]
#10 30.45       at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.<init>(DatabaseInformationImpl.java:60) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final]
#10 30.45       at org.hibernate.tool.schema.internal.Helper.buildDatabaseInformation(Helper.java:183) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final]
#10 30.45       at org.hibernate.tool.schema.internal.AbstractSchemaValidator.doValidation(AbstractSchemaValidator.java:68) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final]
#10 30.45       at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:200) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final]
#10 30.45       at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:81) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final]
#10 30.45       at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:335) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final]
#10 30.45       at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:471) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final]
#10 30.45       at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1498) ~[hibernate-core-5.6.3.Final.jar:5.6.3.Final]
#10 30.45       at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:58) ~[spring-orm-5.3.14.jar:5.3.14]
#10 30.45       at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) ~[spring-orm-5.3.14.jar:5.3.14]
#10 30.45       at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) ~[spring-orm-5.3.14.jar:5.3.14]
#10 30.45       ... 86 common frames omitted
#10 30.45 
#10 30.48 [ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 3.495 s <<< FAILURE! - in de.krayadev.taskitory.TaskitoryApplicationTests
#10 30.49 [ERROR] contextLoads  Time elapsed: 0.007 s  <<< ERROR!
#10 30.49 java.lang.IllegalStateException: Failed to load ApplicationContext
#10 30.49 Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is java.lang.RuntimeException: Driver org.postgresql.Driver claims to not accept jdbcUrl, jdbc:postgresql://${DB_ADDR_ALIAS}:${DB_PORT}/${DB_NAME}
#10 30.49 Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is java.lang.RuntimeException: Driver org.postgresql.Driver claims to not accept jdbcUrl, jdbc:postgresql://${DB_ADDR_ALIAS}:${DB_PORT}/${DB_NAME}
#10 30.49 Caused by: java.lang.RuntimeException: Driver org.postgresql.Driver claims to not accept jdbcUrl, jdbc:postgresql://${DB_ADDR_ALIAS}:${DB_PORT}/${DB_NAME}

我试过的:

  1. 我尝试构建 Spring 引导应用程序,其中 DB 容器已启动,运行 并已停止。在这两种情况下都会出现此错误。
  2. 我尝试了主机的所有组合 ("db", "localhost", ".env-variable ") 和端口 ("5432", "60000", ".env-variable") 对于 jdbc-url.
#10 28.84 Caused by: java.net.UnknownHostException: db
#10 28.84       at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:567) ~[na:na]
#10 28.84       at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:327) ~[na:na]
#10 28.84       at java.base/java.net.Socket.connect(Socket.java:633) ~[na:na]
#10 28.84       at org.postgresql.core.PGStream.createSocket(PGStream.java:231) ~[postgresql-42.2.18.jar:42.2.18]
#10 28.84       at org.postgresql.core.PGStream.<init>(PGStream.java:95) ~[postgresql-42.2.18.jar:42.2.18]
#10 28.84       at org.postgresql.core.v3.ConnectionFactoryImpl.tryConnect(ConnectionFactoryImpl.java:98) ~[postgresql-42.2.18.jar:42.2.18]
#10 28.84       at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:213) ~[postgresql-42.2.18.jar:42.2.18]
#10 28.84       ... 115 common frames omitted
#10 28.84 
#10 28.87 [ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 4.365 s <<< FAILURE! - in de.krayadev.taskitory.TaskitoryApplicationTests
#10 28.87 [ERROR] contextLoads  Time elapsed: 0.005 s  <<< ERROR!
#10 28.87 java.lang.IllegalStateException: Failed to load ApplicationContext
#10 28.87 Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to open JDBC Connection for DDL execution
#10 28.87 Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to open JDBC Connection for DDL execution
#10 28.87 Caused by: org.hibernate.exception.JDBCConnectionException: Unable to open JDBC Connection for DDL execution
#10 28.87 Caused by: org.postgresql.util.PSQLException: The connection attempt failed.
#10 28.87 Caused by: java.net.UnknownHostException: db
#10 29.47 Caused by: java.net.ConnectException: Connection refused
#10 29.47       at java.base/sun.nio.ch.Net.pollConnect(Native Method) ~[na:na]
#10 29.47       at java.base/sun.nio.ch.Net.pollConnectNow(Net.java:672) ~[na:na]
#10 29.47       at java.base/sun.nio.ch.NioSocketImpl.timedFinishConnect(NioSocketImpl.java:542) ~[na:na]
#10 29.47       at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:597) ~[na:na]
#10 29.47       at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:327) ~[na:na]
#10 29.47       at java.base/java.net.Socket.connect(Socket.java:633) ~[na:na]
#10 29.47       at org.postgresql.core.PGStream.createSocket(PGStream.java:231) ~[postgresql-42.2.18.jar:42.2.18]
#10 29.47       at org.postgresql.core.PGStream.<init>(PGStream.java:95) ~[postgresql-42.2.18.jar:42.2.18]
#10 29.47       at org.postgresql.core.v3.ConnectionFactoryImpl.tryConnect(ConnectionFactoryImpl.java:98) ~[postgresql-42.2.18.jar:42.2.18]
#10 29.47       at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:213) ~[postgresql-42.2.18.jar:42.2.18]
#10 29.47       ... 115 common frames omitted
#10 29.47 
#10 29.49 [ERROR] Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 5.539 s <<< FAILURE! - in de.krayadev.taskitory.TaskitoryApplicationTests
#10 29.49 [ERROR] contextLoads  Time elapsed: 0.005 s  <<< ERROR!
#10 29.49 java.lang.IllegalStateException: Failed to load ApplicationContext
#10 29.49 Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to open JDBC Connection for DDL execution
#10 29.49 Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to open JDBC Connection for DDL execution
#10 29.49 Caused by: org.hibernate.exception.JDBCConnectionException: Unable to open JDBC Connection for DDL execution
#10 29.49 Caused by: org.postgresql.util.PSQLException: Connection to localhost:60000 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
#10 29.49 Caused by: java.net.ConnectException: Connection refused

如果您遗漏了解决我问题的任何内容,请随时发表评论。

您应该像对 db:

一样将 .env 变量传递给后端容器
  backend:
    environment:
      DB_ADDR_ALIAS: '${DB_ADDR_ALIAS}'
      DB_PORT: '${DB_PORT}'

对于名称解析部分,我会尝试“taskitory-db”。

我想我用 application.properties 文件中的 .env-variables 解决了这部分问题。为此,我使用 ARG 命令在 Spring 引导应用程序的 Dockerfile 中为构建时间定义了环境变量。我使用 .env 变量在 Docker-compose.yml 中初始化了这些参数:

Dockerfile

FROM maven:3.8.4-openjdk-17-slim AS build
ARG DB_ADDR_ALIAS
ARG DB_PORT
ARG DB_NAME
ARG DB_CLIENT_USER
ARG DB_CLIENT_PW

Docker-compose.yml

backend:
    container_name: taskitory-backend
    build:
      context: .
      args:
        - DB_ADDR_ALIAS=${DB_ADDR_ALIAS}
        - DB_PORT=${DB_PORT}
        - DB_NAME=${DB_NAME}
        - DB_CLIENT_USER=${DB_CLIENT_USER}
        - DB_CLIENT_PW=${DB_CLIENT_PW}

.env 文件

DB_ADDR_ALIAS=db
DB_PORT=5432
DB_NAME=Taskitory
DB_CLIENT_USER=client
DB_CLIENT_PW=*********

application.properties

spring.datasource.url = jdbc:postgresql://${DB_ADDR_ALIAS}:${DB_PORT}/${DB_NAME}
spring.datasource.username = ${DB_CLIENT_USER}
spring.datasource.password = ${DB_CLIENT_PW}

但是,仍然存在 Spring 引导应用程序在构建时无法识别主机“db”的问题:Caused by: java.net.UnknownHostException: db 。在我的研究过程中,我得出的结论是,在“application.properties”文件中只有组合“jdbc:postgresql://db: 5432/Taskitory”对于字段“spring.datasource.url”是适用的。在后端容器内部使用 localhost 将引用后端容器本身,因此不适用于连接到数据库容器。

我通过将 -DskipTests=true 添加到我的 DOCKERFILE 中的 mvn package 解决了这个问题:

FROM maven:3.8.4-openjdk-17-slim AS build
ARG DATABASE_ADDR_ALIAS
ARG DATABASE_PORT
ARG DATABASE_NAME
ARG DATABASE_CLIENT_USER
ARG DATABASE_CLIENT_PW
COPY src /Taskitory/src
COPY pom.xml /Taskitory
RUN mvn -f /Taskitory/pom.xml clean package -DskipTests=true

问题是 Spring 引导应用程序在构建时当然找不到 docker 网络。因此,应用程序不能 运行 运行 测试。