【问题标题】:How to connect to a postgres database when having two docker-compose files?有两个 docker-compose 文件时如何连接到 postgres 数据库?
【发布时间】:2021-04-14 17:18:42
【问题描述】:

首先我使用 Dockerfile 构建了一个镜像:

FROM openjdk:8-jdk-alpine
ARG JAR_FILE=target/*-SNAPSHOT.jar
ADD ${JAR_FILE} app.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]

因为我有两个 docker-compose 文件,一个用于生产:

version: "3"

services:
    app:
      image: "demo:latest"
      container_name: demo-production-api
      restart: always
      depends_on:
        - "productiondb"
      environment:
        - SPRING_DATASOURCE_URL=jdbc:postgresql://productiondb:5432/testdb
        - SPRING_DATASOURCE_HIKARI_JDBC_URL=jdbc:postgresql://productiondb:5432/testdb
        - SPRING_DATASOURCE_USER=tester
        - SPRING_DATASOURCE_PASSWORD=test
        - SPRING_JPA_HIBERNATE_DDL_AUTO=update
      ports:
        - "8440:8443"

    productiondb:
      image: "postgres:latest"
      container_name: productiondb
      ports:
        - "5430:5432"
      environment:
        - POSTGRES_USER=postgres
        - POSTGRES_PASSWORD=postgres
      volumes:
        - postgres-db-production:/usr/local/var/postgres


volumes:
  postgres-db-production:

还有一个用于开发:

version: "3"

services:
  app:
    image: "demo:latest"
    container_name: demo-develop-api
    restart: always
    depends_on:
      - "developdb"
    environment:
      - SPRING_DATASOURCE_URL=jdbc:postgresql://developdb:5432/testdb
      - SPRING_DATASOURCE_HIKARI_JDBC_URL=jdbc:postgresql://developdb:5432/testdb
      - SPRING_DATASOURCE_USER=tester
      - SPRING_DATASOURCE_PASSWORD=test
      - SPRING_JPA_HIBERNATE_DDL_AUTO=update
    ports:
      - "8441:8443"

  developdb:
    image: "postgres:latest"
    container_name: developdb
    ports:
      - "5431:5432"
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
    volumes:
    - postgres-db-develop:/usr/local/var/postgres


volumes:
  postgres-db-develop:

我使用以下方法构建两个图像:

docker-compose -p demo-production-api -f docker-compose.yml up -d && docker-compose -p demo-develop-api -f docker-compose-develop.yml up -d

现在我可以同时构建 demo-develop-api 和 demo-production-api 两个环境,来自 demo-develop-api docker 镜像的 Spring Boot 应用程序使用以下命令运行:

docker run -it demo-develop-api

应用程序运行,但我不断收到此错误:

原因:java.net.UnknownHostException: productiondb

application.properties 文件中的数据库主机从 localhost 更改为 productiondb 后发生上述错误,首先我得到以下信息:

org.postgresql.util.PSQLException:连接到 localhost:5432 拒绝了。检查主机名和端口是否正确,以及 postmaster 正在接受 TCP/IP 连接。

为什么会出现此问题或原因是什么? 如何解决此类问题?

【问题讨论】:

    标签: postgresql spring-boot docker docker-compose


    【解决方案1】:

    据我所知,问题可能是您已将端口 5430 和 5431 绑定到 5432,并且您可能在 application.resources 文件中将端口设置为 5432。您的应用程序应该尝试使用端口 5430 或 5431 分别用于生产和开发连接到数据库。请检查并尝试这个。因此,请在 application.resources 文件中更改端口。

    【讨论】:

    • 54305431 是已经映射到 5432 的容器的内部端口,它们必须不同,这样我才能获得两个单独的数据库容器。至于资源中application.properties文件中指定的端口,它必须是已经映射到docker-compose文件中的5430:54325431:5432的外部端口。
    • 我从两个 postgres 数据库容器 shell 中进行了 netstat,我只能看到端口 5432 处于 LISTEN 模式。
    • 5430 和 5431 不是容器的内部端口,它们是容器的内部端口(在我们的例子中是 5432)应该在主机系统上暴露的端口。他们基本上被绑定了。但是我意识到您还没有创建名为 testdb 的数据库。(您可以看到您尚未定义环境变量 POSTGRES_DB=testdb ,通过使用此变量,将在启动期间创建具有上述名称的默认数据库)。因此,您将获得 UnknownHostException)。所以把这个环境变量添加到docker-compose中试试。
    • 是的,谢谢先生。我发现在我注意到容器在我在 IRC 聊天中遇到的人的帮助下重新启动后,因为 Spring Boot 应用程序由于一开始没有创建 testdb 而崩溃。我唯一想弄清楚的是如何通过 127.0.0.1:8441 访问容器,因为我现在可以看到端口 8443 正在侦听映射到 0.0.0.0:8441 主机端口的容器内,但我无法只能通过 192.168.99.100:8014 从主机通过 127.0.0.1:8441 访问它。
    • 因为我计划通过域名从外部访问它,例如coolsite.com:8441/api/v1/login
    【解决方案2】:

    所以经过长时间的调试和试验,希望这可以节省人们的时间,事实证明,容器内的 Spring Boot 应用程序正在重新启动运行并崩溃,没有任何错误,这让我更加困惑为什么它没有监听或打开端口。我什至怀疑它可能是防火墙或其他东西。所以基本上我只是尝试通过以下方式从容器中获取外壳:

    docker exec -it <container id or image> sh

    注意:由于我使用的是图像openjdk:8-jdk-alpine,所以不要在下面做,你不会得到一个shell:

    docker exec -it <container id or image> bash

    然后我尝试通过以下方式获取开放端口列表:

    netstat -tulpn | grep ":8443"

    端口8443未列出,我认为这可能是java程序没有运行的问题,试图执行spring boot,但没有任何错误,shell本身正在退出,这让我更加困惑. 直到我发现容器由于 Spring Boot 崩溃而重新启动。所以我通过将以下属性添加到application.properties 来启用详细模式,然后再次重建图像:

    logging.level.org.springframework.web=DEBUG

    logging.level.org.hibernate=DEBUG

    所以我重试了上面最后的步骤,我得到一个 shell 并执行 app.jar,结果发现数据库 testdb 不存在。

    更新:总结一下我是如何修改我的项目的,我为我的案例创建了两个 Spring Boot 配置文件,一个用于开发application-develop.properties,一个用于生产application-production.properties

    所以在application-develop.properties 里面我把它映射到一个开发postgres 容器的主机和端口:

    spring.datasource.url=jdbc:postgresql://developdb:5432/testdb
    spring.datasource.hikari.jdbc-url=jdbc:postgresql://developdb:5432/testdb
    spring.datasource.username=tester
    spring.jpa.generate-ddl=true
    spring.datasource.password=test
    spring.jpa.database-platform=postgres
    spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQL9Dialect
    spring.jpa.hibernate.ddl-auto=create-drop
    spring.jpa.show-sql=true
    spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
    server.port=8443
    

    对于application-production.properties

    spring.datasource.url=jdbc:postgresql://productiondb:5432/testdb
    spring.datasource.hikari.jdbc-url=jdbc:postgresql://productiondb:5432/testdb
    spring.datasource.username=tester
    spring.jpa.generate-ddl=true
    spring.datasource.password=test
    spring.jpa.database-platform=postgres
    spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQL9Dialect
    spring.jpa.hibernate.ddl-auto=create-drop
    spring.jpa.show-sql=true
    spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
    server.port=8443
    

    在开发的 docker-compose 文件中,我只是将 Spring Boot 配置文件环境变量定义为:

    environment:
      - SPRING_PROFILES_ACTIVE=develop
    

    对于生产 docker-compose 文件,我将其定义如下:

    environment:
      - SPRING_PROFILES_ACTIVE=production
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-13
      • 1970-01-01
      • 2020-04-27
      • 1970-01-01
      • 2018-12-21
      • 1970-01-01
      • 2021-08-15
      • 2020-06-28
      相关资源
      最近更新 更多