【问题标题】:Spring cannot connect to postgres when using docker使用docker时Spring无法连接到postgres
【发布时间】:2021-12-11 15:22:56
【问题描述】:

我正在尝试将使用另一个容器化 Postgres 数据库的 Spring Boot 项目容器化,但似乎 Spring 项目无法连接到数据库,因为它无法解析主机名。

Dockerfile:

FROM maven:3.6.0-jdk-11
WORKDIR /app
COPY . /app
RUN mvn clean install spring-boot:run -q

Docker 撰写:

version: "3.7"

services:
  postgres:
    image: postgres
    container_name: db
    expose:
      - "5432"
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: nanobox
    networks:
      - app-network
  
  backend:
    restart: always
    build:
      context: nanobox
    volumes:
      - ./nanobox:/app
    environment:
      - SECRET=bigsecret
    ports:
      - 8081:8081
    networks:
      - app-network
    depends_on:
      - postgres


networks:
  app-network:
    driver: bridge

application.properties:

logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
#debug=false

spring.datasource.platform=postgres
spring.datasource.url=jdbc:postgresql://postgres:5432/nanobox
spring.datasource.username=postgres
spring.datasource.password=postgres
spring.jpa.generate-ddl=true
spring.jpa.database=postgresql
spring.jpa.hibernate.ddl-auto=update
#spring.jpa.properties.hibernate.jdbc.lob.not_contextual_creation=true
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
debug=true
spring.mvc.log-request-details=true
auth.secret={SECRET}
storage.prefix = /tmp/uploads/

docker compose up 失败,但出现以下异常:

#8 44.67 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
    [..]
#8 44.67 Caused by: org.hibernate.exception.JDBCConnectionException: Unable to open JDBC Connection for DDL execution
    [..]
#8 44.68 Caused by: org.postgresql.util.PSQLException: The connection attempt failed.
    [..]
#8 44.68 Caused by: java.net.UnknownHostException: postgres

似乎由于某种原因docker compose拒绝在Spring应用程序之前启动postgres容器,甚至命令:

docker compose up postgres backend

结果:

[+] Building 8.3s (8/8) FINISHED                                                                                                                                                                                                                                                                                            
 => [internal] load build definition from Dockerfile                                                                                                                                                                                                                                                                   0.0s
 => => transferring dockerfile: 31B                                                                                                                                                                                                                                                                                    0.0s
 => [internal] load .dockerignore                                                                                                                                                                                                                                                                                      0.0s
 => => transferring context: 2B                                                                                                                                                                                                                                                                                        0.0s
 => [internal] load metadata for docker.io/library/maven:3.6.0-jdk-11                                                                                                                                                                                                                                                  1.5s
 => [1/4] FROM docker.io/library/maven:3.6.0-jdk-11@sha256:6a0430ded2cfaba7e16080f4cc097c9c65d1406b3b235d0fcfcfd84c354c4177                                                                                                                                                                                            0.0s
 => [internal] load build context                                                                                                                                                                                                                                                                                      0.0s
 => => transferring context: 18.55kB                                                                                                                                                                                                                                                                                   0.0s
 => CACHED [2/4] WORKDIR /app                                                                                                                                                                                                                                                                                          0.0s
 => CACHED [3/4] COPY . /app    

【问题讨论】:

  • 你有来自 postgres 容器的日志吗?是否正常启动?
  • 这实际上是一个好问题......似乎由于某种原因它甚至没有被 docker-compose 命令启动。
  • 你能从你的 Dockerfile 中的 RUN 命令中删除 -q 吗?它可能隐藏了一个错误。
  • 我添加它是因为它淹没了我的日志并且它们会达到限制,隐藏与无法连接到数据库相关的实际错误。 :#8 44.19 [output clipped, log limit 1MiB reached]
  • 尝试将 spring.datasource.url=jdbc:postgresql://postgres:5432/nanobox 更改为 spring.datasource.url=jdbc:postgresql://db:5432/nanobox。您的 docker compose 的 postgres 容器名称为 db,其中 application.properties 未指向此容器名称

标签: java spring postgresql docker docker-compose


【解决方案1】:

您正在尝试从 Dockerfile RUN 指令运行 mvn spring-boot:run;这发生在您尝试构建映像时,而不是在您稍后运行容器时。 (这类似于使用javac 编译源文件和java 运行构建的类文件之间的区别。)由于超出此答案范围的原因,构建阶段无法连接到其他容器,即使它们在同一个 docker-compose.yml 文件中声明。

将 Dockerfile 分成两行来构建应用程序,然后将其作为主容器命令运行:

FROM maven:3.6.0-jdk-11
WORKDIR /app
COPY . .      # (don't repeat /app directory name)

# At build time, only compile the application but do not run it
RUN mvn clean install

# When you launch the container, this will be the main command
CMD mvn spring-boot:run

【讨论】:

  • RUN mvn clean install -q 导致相同的错误.. CMD 永远不会到达。似乎 postgres 容器由于某种原因没有在后台启动。
  • 仅仅编译你的应用程序不需要运行数据库,不是吗?
  • 老实说,我不明白你的意思,可能我还是个初学者,在谈到 Spring 和 Docker 的理论知识时。我想说的是,即使您进行了更改,它也不起作用。主机名未解析,因为 postgres 容器未启动。
  • mvn install 在做什么需要连接到数据库?
  • 我不知道!我唯一知道的是它失败了,所以我的问题没有解决。
【解决方案2】:

@david-maze 的解决方案对我来说几乎是好的。但是,我用下面的 Dockerfile 解决了这个问题:

FROM maven:3.6.0-jdk-11
WORKDIR /app
COPY . .

# At build time, only compile the application but do not run it
RUN mvn clean package -DskipTests -q

# When you launch the container, this will be the main command
CMD mvn spring-boot:run

还必须为数据库容器添加别名:

postgres:
    image: postgres
    container_name: db
    expose:
      - "5432"
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: nanobox
      networks:
        some-net:
          aliases:
            - auth-module.dev

Maven 正在运行导致容器启动失败的测试,因为没有数据库。

【讨论】: