Docker:Springboot 容器无法连接到 PostgreSql 容器

Posted

技术标签:

【中文标题】Docker:Springboot 容器无法连接到 PostgreSql 容器【英文标题】:Docker: Springboot container cannot connect to PostgreSql Container 【发布时间】:2021-02-09 16:44:08 【问题描述】:

我正在构建一个使用 PostgreSQL 和 docker-compose 的 Spring Boot 应用程序。 当我使用 docker-compose up --build 运行容器时,我的 Spring Boot 应用程序无法启动,因为它找不到 PostgreSQL 容器的主机名。

Spring Boot Dockerfile

FROM maven:3.6.3-openjdk-14-slim AS build  
COPY src /usr/src/app/src  
COPY pom.xml /usr/src/app  
RUN mvn -f /usr/src/app/pom.xml clean package

FROM openjdk:14-slim
COPY --from=build /usr/src/app/target/server-0.0.1-SNAPSHOT.jar /usr/app/server-0.0.1-SNAPSHOT.jar
EXPOSE 9000  
ENTRYPOINT ["java","-jar","/usr/app/server-0.0.1-SNAPSHOT.jar"]

docker-compose.yml

version: '3'

services:
  db:
    image: postgres
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: my_db
    ports:
      - "5432:5432"
    volumes:
      - db-data:/var/lib/postgresql/data
    networks:
      - db-network
    restart: always

  server:
    build: './server'
    depends_on:
      - db
    restart: always
    ports:
      - "9000:9000"
    networks:
      - db-network
    volumes:
      - ./server:/server


networks:
  db-network:

volumes:
  db-data:

application.properties

spring.datasource.url=jdbc:postgresql://db:5432/my_db
spring.datasource.username=postgres
spring.datasource.password=postgres

错误输出

Caused by: java.net.UnknownHostException: db

我的猜测是在 Spring Boot Dockerfile 的构建阶段还没有创建 docker-compose 的虚拟网络。 关于如何解决这个问题的任何想法?

【问题讨论】:

【参考方案1】:

这里有很多信息:https://docs.docker.com/compose/networking/

在 Web 容器中,您与 db 的连接字符串如下所示 postgres://db:5432,以及来自主机的连接字符串 看起来像 postgres://DOCKER_IP:8001。

这就是说 db:5432 可以在 docker-compose.yaml 中使用,并且 IP 地址将被传递(不是“db”),但在应用程序代码中外部使用它是行不通的。但是,您可以从 docker-compose.yaml db 作为应用程序输入变量传递,您的应用程序可以将其填充到配置文件中。这将使您能够连接。

像这样的外部化配置是相当普遍的做法,所以应该是一个相对容易的修复。

例如:

Docker-compose.yaml

version: '3'

services:
  db:
    container_name: db
    image: postgres
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: my_db
    ports:
      - "5432:5432"
    volumes:
      - db-data:/var/lib/postgresql/data
    networks:
      - db-network
    restart: always

  server:
    build: './server'
    depends_on:
      - db
    environment:
      DB_HOST: db # untested, but there should be a way to pass this in
      DB_PORT: 5432
      DB_DATABASE: my_db
      DB_USER: postgres
      DB_PASSWORD: postgres
    restart: always
    ports:
      - "9000:9000"
    networks:
      - db-network
    volumes:
      - ./server:/server


networks:
  db-network:

volumes:
  db-data:

然后有一个位于src/main/java/resources/application.properties下的application.properties文件

spring.datasource.url=jdbc:postgresql://$DB_HOST:$DB_PORT/$DB_DATABASE
spring.datasource.username=$DB_USERNAME
spring.datasource.password=$DB_PASSWORD

【讨论】:

我尝试了您的解决方案,但环境变量甚至没有加载。我收到错误java.net.UnknownHostException: $DB_HOST,好像application.properties 没有用db 替换$DB_HOST 旋转时是否在容器内?您可以检查docker exec -it [containerId] bash,它可以让您进入容器,然后env 列出环境变量...如果DB_HOST 未正确设置为环境变量,它将不会在 application.properties 中被替换文件。一旦你验证了它的设置,变量应该级联到你的应用程序中 将整个项目复制到镜像中,添加WORKDIR /usr/src/app,那么应该可以添加标准的RUN mvn clean package。除非pom.xml 中有错误,否则只要 pom.xml 在您指定的目录中,该命令就应该运行。即不要只做COPY src /usr/src/app/src,而是做COPY . /usr/src/app 我刚刚检查过,DB_HOST 设置不正确,这很奇怪,因为它是在我的 docker-compose 中定义的 今晚我会尝试测试一下 - 获得最小的工作版本应该不会太难【参考方案2】:

This post 完全解决了我的问题。 事实证明,maven 在构建 .jar 文件时试图建立与数据库的连接。我所要做的就是用这行 RUN mvn -f /usr/src/app/pom.xml clean package -DskipTests 修改我的 Dockerfile。

【讨论】:

【参考方案3】:

请注意,在构建图像时,该服务将无法访问数据库,因为它尚未运行。只有在构建镜像并且容器运行之后,服务才可以访问。因此,当您尝试将主机作为 db 传递时,它在构建阶段尚不可用。只有在 db 容器开始运行时才可用。

【讨论】:

以上是关于Docker:Springboot 容器无法连接到 PostgreSql 容器的主要内容,如果未能解决你的问题,请参考以下文章

Springboot 应用程序无法使用 docker-compose 连接到 MongoDB 容器

Spring boot JDBC无法连接到docker容器中的mysql

无法从 docker 容器内的 Spring Boot 连接到 Redis

无法从 Docker 容器连接到外部 SQL Server

Spring Boot + MySQL + Docker Compose - 无法使 Spring Boot 连接到 MySQL

Docker 中的 Postgres 服务器无法连接到 Spring Boot 应用程序