简体   繁体   English

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

[英]Docker: Springboot container cannot connect to PostgreSql Container

I am building a Spring Boot application which uses PostgreSQL with docker-compose. When I run my containers using docker-compose up --build , my Spring Boot application fails to start because it does not find the PostgreSQL container's hostname.我正在构建一个 Spring Boot 应用程序,它使用 PostgreSQL 和 docker-compose。当我使用docker-compose up --build运行我的容器时,我的 Spring Boot 应用程序无法启动,因为它没有找到 883415717947.8 容器的主机名

Spring Boot Dockerfile Spring 开机 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 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应用程序.properties

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

Error output错误 output

Caused by: java.net.UnknownHostException: db

My guess is that docker-compose's virtual.network isn't created yet during the build stage of the Spring Boot Dockerfile. Any idea on how to solve this issue?我的猜测是在 Spring 引导 Dockerfile 的构建阶段尚未创建 docker-compose 的 virtual.network。关于如何解决此问题的任何想法?

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

Within the web container, your connection string to db would look like postgres://db:5432, and from the host machine, the connection string would look like postgres://{DOCKER_IP}:8001.在 web 容器中,您到 db 的连接字符串看起来像 postgres://db:5432,而从主机看,连接字符串看起来像 postgres://{DOCKER_IP}:8001。

What this is saying is db:5432 is fine to use within docker-compose.yaml and the IP address will be passed (not "db"), but using it externally within your application code isn't going to work.这就是说 db:5432 可以在 docker-compose.yaml 中使用,并且将传递 IP 地址(不是“db”),但在您的应用程序代码外部使用它是行不通的。 You could however pass from docker-compose.yaml db as an application input variable, which your application could fill in in the configuration file.但是,您可以从docker-compose.yaml db作为应用程序输入变量传递,您的应用程序可以将其填写到配置文件中。 This would enable you then to connect.这将使您能够连接。

Externalising configuration like this is fairly common practice so should be a relatively easy fix.像这样外部化配置是相当普遍的做法,因此应该是一个相对容易的修复。

eg:例如:

Docker-compose.yaml 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:

Then have an application.properties file located under src/main/java/resources/application.properties然后在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}

This post completely solved my issue. 这篇文章彻底解决了我的问题。 It turns out that maven was trying to establish the connection to the database while building the.jar file.事实证明,maven 在构建 .jar 文件时试图建立与数据库的连接。 All I had to do is modify my Dockerfile with this line RUN mvn -f /usr/src/app/pom.xml clean package -DskipTests .我所要做的就是用这条线修改我的 Dockerfile RUN mvn -f /usr/src/app/pom.xml clean package -DskipTests

Please do note while building the images the service will not have access to the database as it is not yet running.请注意,在构建图像时,该服务将无法访问数据库,因为它尚未运行。 Only after the images are built and the containers are running do the services have access.只有在构建镜像并且容器运行之后,服务才能访问。 So when you try to pass a host as db, it is not yet available in the build stage.因此,当您尝试将主机作为 db 传递时,它在构建阶段尚不可用。 It is available only once the db container starts running.它仅在数据库容器开始运行后可用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM