Spring в docker контейнере не может подключиться к базе данных Postgresql

Я хочу обернуть свой spring-проект в докер чтобы запустить на сервере, но когда я выполняю:

docker compose up

Я получаю ошибку:

portfolio-back   | 2024-10-30T10:09:01.020Z  WARN 1 --- [portfolio] [           main] org.hibernate.orm.deprecation            : HHH90000025: PostgreSQLDialect does not need to be specified explicitly using 'hibernate.dialect' (remove the property setting and it will be selected by default)
portfolio-back   | 2024-10-30T10:09:07.601Z  INFO 1 --- [portfolio] [           main] o.h.e.t.j.p.i.JtaPlatformInitiator       : HHH000489: No JTA platform available (set 'hibernate.transaction.jta.platform' to enable JTA platform integration)
portfolio-back   | 2024-10-30T10:09:07.718Z  INFO 1 --- [portfolio] [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting...
portfolio-back   | 2024-10-30T10:09:08.737Z  WARN 1 --- [portfolio] [           main] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 0, SQLState: 08001
portfolio-back   | 2024-10-30T10:09:08.738Z ERROR 1 --- [portfolio] [           main] o.h.engine.jdbc.spi.SqlExceptionHelper   : Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
portfolio-back   | 2024-10-30T10:09:08.750Z ERROR 1 --- [portfolio] [           main] j.LocalContainerEntityManagerFactoryBean : Failed to initialize JPA EntityManagerFactory: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to open JDBC Connection for DDL execution [Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.] [n/a]
portfolio-back   | 2024-10-30T10:09:08.754Z  WARN 1 --- [portfolio] [           main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to open JDBC Connection for DDL execution [Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.] [n/a]
portfolio-back   | 2024-10-30T10:09:08.759Z  INFO 1 --- [portfolio] [           main] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]
portfolio-back   | 2024-10-30T10:09:08.834Z  INFO 1 --- [portfolio] [           main] .s.b.a.l.ConditionEvaluationReportLogger :
portfolio-back   |
portfolio-back   | Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
portfolio-back   | 2024-10-30T10:09:08.937Z ERROR 1 --- [portfolio] [           main] o.s.boot.SpringApplication               : Application run failed
portfolio-back   |
portfolio-back   | org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to open JDBC Connection for DDL execution [Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.] [n/a]
portfolio-back   |      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1806) ~[spring-beans-6.1.13.jar!/:6.1.13]
portfolio-back   |      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:600) ~[spring-beans-6.1.13.jar!/:6.1.13]
portfolio-back   |      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.13.jar!/:6.1.13]
portfolio-back   |      at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) ~[spring-beans-6.1.13.jar!/:6.1.13]
portfolio-back   |      at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.13.jar!/:6.1.13]
portfolio-back   |      at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) ~[spring-beans-6.1.13.jar!/:6.1.13]
portfolio-back   |      at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205) ~[spring-beans-6.1.13.jar!/:6.1.13]
portfolio-back   |      at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:954) ~[spring-context-6.1.13.jar!/:6.1.13]
portfolio-back   |      at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:625) ~[spring-context-6.1.13.jar!/:6.1.13]
portfolio-back   |      at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) ~[spring-boot-3.3.4.jar!/:3.3.4]
portfolio-back   |      at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-3.3.4.jar!/:3.3.4]
portfolio-back   |      at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) ~[spring-boot-3.3.4.jar!/:3.3.4]
portfolio-back   |      at org.springframework.boot.SpringApplication.run(SpringApplication.java:335) ~[spring-boot-3.3.4.jar!/:3.3.4]
portfolio-back   |      at org.springframework.boot.SpringApplication.run(SpringApplication.java:1363) ~[spring-boot-3.3.4.jar!/:3.3.4]
portfolio-back   |      at org.springframework.boot.SpringApplication.run(SpringApplication.java:1352) ~[spring-boot-3.3.4.jar!/:3.3.4]
portfolio-back   |      at com.example.portfolio.PortfolioApplication.main(PortfolioApplication.java:24) ~[!/:2.1.1]
portfolio-back   |      at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[na:na]
portfolio-back   |      at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[na:na]
portfolio-back   |      at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:102) ~[portfolio-2.1.1.jar:2.1.1]
portfolio-back   |      at org.springframework.boot.loader.launch.Launcher.launch(Launcher.java:64) ~[portfolio-2.1.1.jar:2.1.1]
portfolio-back   |      at org.springframework.boot.loader.launch.JarLauncher.main(JarLauncher.java:40) ~[portfolio-2.1.1.jar:2.1.1]
portfolio-back   | Caused by: jakarta.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to open JDBC Connection for DDL execution [Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.] [n/a]
portfolio-back   |      at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:421) ~[spring-orm-6.1.13.jar!/:6.1.13]
portfolio-back   |      at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:396) ~[spring-orm-6.1.13.jar!/:6.1.13]
portfolio-back   |      at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:366) ~[spring-orm-6.1.13.jar!/:6.1.13]
portfolio-back   |      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1853) ~[spring-beans-6.1.13.jar!/:6.1.13]
portfolio-back   |      at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1802) ~[spring-beans-6.1.13.jar!/:6.1.13]
portfolio-back   |      ... 20 common frames omitted
portfolio-back   | Caused by: org.hibernate.exception.JDBCConnectionException: Unable to open JDBC Connection for DDL execution [Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.] [n/a]
portfolio-back   |      at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:100) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final]
portfolio-back   |      at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:58) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final]
portfolio-back   |      at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:108) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final]
portfolio-back   |      at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:94) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final]
portfolio-back   |      at org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl.getIsolatedConnection(DdlTransactionIsolatorNonJtaImpl.java:74) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final]
portfolio-back   |      at org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl.getIsolatedConnection(DdlTransactionIsolatorNonJtaImpl.java:39) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final]
portfolio-back   |      at org.hibernate.tool.schema.internal.exec.ImprovedExtractionContextImpl.getJdbcConnection(ImprovedExtractionContextImpl.java:63) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final]
portfolio-back   |      at org.hibernate.tool.schema.extract.spi.ExtractionContext.getQueryResults(ExtractionContext.java:43) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final]
portfolio-back   |      at org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl.extractMetadata(SequenceInformationExtractorLegacyImpl.java:39) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final]
portfolio-back   |      at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.initializeSequences(DatabaseInformationImpl.java:66) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final]
portfolio-back   |      at org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl.<init>(DatabaseInformationImpl.java:60) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final]
portfolio-back   |      at org.hibernate.tool.schema.internal.Helper.buildDatabaseInformation(Helper.java:185) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final]
portfolio-back   |      at org.hibernate.tool.schema.internal.AbstractSchemaMigrator.doMigration(AbstractSchemaMigrator.java:100) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final]
portfolio-back   |      at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.performDatabaseAction(SchemaManagementToolCoordinator.java:280) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final]
portfolio-back   |      at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.lambda$process$5(SchemaManagementToolCoordinator.java:144) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final]
portfolio-back   |      at java.base/java.util.HashMap.forEach(HashMap.java:1429) ~[na:na]
portfolio-back   |      at org.hibernate.tool.schema.spi.SchemaManagementToolCoordinator.process(SchemaManagementToolCoordinator.java:141) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final]
portfolio-back   |      at org.hibernate.boot.internal.SessionFactoryObserverForSchemaExport.sessionFactoryCreated(SessionFactoryObserverForSchemaExport.java:37) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final]
portfolio-back   |      at org.hibernate.internal.SessionFactoryObserverChain.sessionFactoryCreated(SessionFactoryObserverChain.java:35) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final]
portfolio-back   |      at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:322) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final]
portfolio-back   |      at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:457) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final]
portfolio-back   |      at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:1506) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final]
portfolio-back   |      at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:75) ~[spring-orm-6.1.13.jar!/:6.1.13]
portfolio-back   |      at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:390) ~[spring-orm-6.1.13.jar!/:6.1.13]
portfolio-back   |      at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:409) ~[spring-orm-6.1.13.jar!/:6.1.13]
portfolio-back   |      ... 24 common frames omitted
portfolio-back   | Caused by: org.postgresql.util.PSQLException: Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
portfolio-back   |      at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:342) ~[postgresql-42.6.0.jar!/:42.6.0]
portfolio-back   |      at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:54) ~[postgresql-42.6.0.jar!/:42.6.0]
portfolio-back   |      at org.postgresql.jdbc.PgConnection.<init>(PgConnection.java:263) ~[postgresql-42.6.0.jar!/:42.6.0]
portfolio-back   |      at org.postgresql.Driver.makeConnection(Driver.java:443) ~[postgresql-42.6.0.jar!/:42.6.0]
portfolio-back   |      at org.postgresql.Driver.connect(Driver.java:297) ~[postgresql-42.6.0.jar!/:42.6.0]
portfolio-back   |      at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:137) ~[HikariCP-5.1.0.jar!/:na]
portfolio-back   |      at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:360) ~[HikariCP-5.1.0.jar!/:na]
portfolio-back   |      at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:202) ~[HikariCP-5.1.0.jar!/:na]
portfolio-back   |      at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:461) ~[HikariCP-5.1.0.jar!/:na]
portfolio-back   |      at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:550) ~[HikariCP-5.1.0.jar!/:na]
portfolio-back   |      at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:98) ~[HikariCP-5.1.0.jar!/:na]
portfolio-back   |      at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:111) ~[HikariCP-5.1.0.jar!/:na]
portfolio-back   |      at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:122) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final]
portfolio-back   |      at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator$ConnectionProviderJdbcConnectionAccess.obtainConnection(JdbcEnvironmentInitiator.java:439) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final]
portfolio-back   |      at org.hibernate.resource.transaction.backend.jdbc.internal.DdlTransactionIsolatorNonJtaImpl.getIsolatedConnection(DdlTransactionIsolatorNonJtaImpl.java:46) ~[hibernate-core-6.5.3.Final.jar!/:6.5.3.Final]
portfolio-back   |      ... 44 common frames omitted
portfolio-back   | Caused by: java.net.ConnectException: Connection refused
portfolio-back   |      at java.base/sun.nio.ch.Net.pollConnect(Native Method) ~[na:na]
portfolio-back   |      at java.base/sun.nio.ch.Net.pollConnectNow(Net.java:682) ~[na:na]
portfolio-back   |      at java.base/sun.nio.ch.NioSocketImpl.timedFinishConnect(NioSocketImpl.java:542) ~[na:na]
portfolio-back   |      at java.base/sun.nio.ch.NioSocketImpl.connect(NioSocketImpl.java:592) ~[na:na]
portfolio-back   |      at java.base/java.net.SocksSocketImpl.connect(SocksSocketImpl.java:327) ~[na:na]
portfolio-back   |      at java.base/java.net.Socket.connect(Socket.java:751) ~[na:na]
portfolio-back   |      at org.postgresql.core.PGStream.createSocket(PGStream.java:243) ~[postgresql-42.6.0.jar!/:42.6.0]
portfolio-back   |      at org.postgresql.core.PGStream.<init>(PGStream.java:98) ~[postgresql-42.6.0.jar!/:42.6.0]
portfolio-back   |      at org.postgresql.core.v3.ConnectionFactoryImpl.tryConnect(ConnectionFactoryImpl.java:132) ~[postgresql-42.6.0.jar!/:42.6.0]
portfolio-back   |      at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:258) ~[postgresql-42.6.0.jar!/:42.6.0]
portfolio-back   |      ... 58 common frames omitted
portfolio-back   |
portfolio-back exited with code 0

Данная проблема актуальна только для докер-контейнера. Если сменить в application.propeties:

spring.datasource.url=jdbc:postgresql://localhost:5432/portfolio

И выполнить команду:

java -jar target/portfolio-2.1.1.jar

Тогда проект успешно запуститься

Мой docker-compose.yml:

services:
  db:
    image: postgres
    restart: always
    container_name: database

    environment:
      POSTGRES_DB: portfolio
      POSTGRES_USER: <пользователь базы данных>
      POSTGRES_PASSWORD: <пароль базы данных>

    ports:
      - "5432:5432"

  back-end:
    image: portfolio-back
    restart: always
    container_name: portfolio-back

    build:
      context: .
      dockerfile: Dockerfile

    ports:
      - "8000:8000"

    depends_on:
      - db

    volumes:
      - app-log:/app/log

  pgadmin:
    container_name: portfolio-admin
    image: dpage/pgadmin4:7
    restart: always

    environment:
      PGADMIN_DEFAULT_EMAIL: <почта для админки>
      PGADMIN_DEFAULT_PASSWORD: <пароль админки>

    ports:
      - "5050:5050"

    volumes:
      - pgadmin-data:/var/lib/pgadmin

volumes:
  app-log:
  pgadmin-data:

Мой Dockerfile:

FROM maven:3.9.8-eclipse-temurin-21
COPY . .
WORKDIR /app
RUN mvn clean package -DskipTests

FROM openjdk:21
EXPOSE 8000
WORKDIR /app
COPY /target/portfolio-2.1.1.jar .
CMD ["java", "-jar", "portfolio-2.1.1.jar"]

Мой application.properties:

spring.application.name=portfolio
spring.thymeleaf.prefix=classpath:/templates/
server.port=8000
spring.profiles.default=database

spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:postgresql://database:5432/portfolio
spring.datasource.username=<пользователь базы данных>
spring.datasource.password=<пароль базы данных>
spring.datasource.driver-class-name=org.postgresql.Driver
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
spring.sql.init.mode=always
spring.jpa.defer-datasource-initialization=true
#spring.jpa.show-sql: true


spring.servlet.multipart.enabled=true
spring.servlet.multipart.file-size-threshold=1MB
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=100MB

Ответы (1 шт):

Автор решения: Август

Ваше приложение, написаное на Spring, которое находится внутри контейнера, пытается обратиться к localhost:5432, но как результат оно делает запрос на свой же контейнер (свою локальную сеть). То есть, у каждого контейнера свой личный localhost и свои порты, и даже IP.
для того, чтобы обратиться к localhost-у другого контейнера (например, где находится база) есть пару вариантов, но проще всех - это воспользоваться алиасами сети, которую создал для Вас докер. каждый контейнер доступен по адресу [PROTOCOL]://[ИМЯ_КОНТЕЙНЕРА]:[PORT], где имя контейнера - это имя, которое использовалось в конфигурации docker-compose.yaml файла.
то есть, чтобы обратиться к контейнеру базы из контейнера, где находится приложение Spring, Вы можете прописать postgresql://db:5432/portfolio.

→ Ссылка