无法从另一个容器连接到 Postgres 容器

Posted

技术标签:

【中文标题】无法从另一个容器连接到 Postgres 容器【英文标题】:Not able to connect to Postgres container from another container 【发布时间】:2021-04-08 16:09:46 【问题描述】:

这个问题在here、here 和here 被问过很多次,但这些解决方案对我不起作用。

我已经用这个docker-compose.yml 文件创建了一个 Postgres 和一个 AppServer 容器

version: "3.7"
services: 
  db:
    image: postgres:alpine
    container_name: db
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
      POSTGRES_DB: mydb
      POSTGRES_INITDB_ARGS: '-A md5'
    volumes:
      - ./pgdata:/var/lib/postgressql/data
    ports:
      - "5432:5432"
  api:
    build: api
    container_name: api
    volumes:
      - ./database/migrations:/migrations
    ports:
      - "8080:8080"
    links:
      - db
    depends_on:
      - db

运行这个之后就可以成功了

docker exec -it db psql -U user mydb

我成功连接到 Postgres。我也可以使用

成功登录到两个容器的终端
docker exec -it api bash
docker exec -it db bash

从 api 的 bash 内部我可以毫无问题地 ping db

但是从我的 api 容器中,我无法建立到 Postgres 数据库的 JDBC 连接。

api    | Flyway Community Edition 7.3.2 by Redgate
api    | ERROR: 
api    | Unable to obtain connection from database (jdbc:postgresql://db:5432/mydb) for user 'user': Connection to db:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
api    | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
api    | SQL State  : 08001
api    | Error Code : 0
api    | Message    : Connection to db:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
api    | 
api    | Caused by: org.postgresql.util.PSQLException: Connection to db:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
api    | Caused by: java.net.ConnectException: Connection refused (Connection refused)

当我可以通过 psql 连接时,为什么连接被拒绝?这是我的飞行路线

flyway.url=jdbc:postgresql://db:5432/mydb
flyway.user=user
flyway.password=password
flyway.locations=filesystem:/migrations

编辑:: 因此,如果我等待一段时间后从docker exec -it api bash 执行flyway migrate,一切正常。我认为上面发生的事情是我的flyway migrate 命令甚至在数据库准备好之前就在运行。

为什么会这样?因为我已经指定了依赖项,所以我的 API 容器应该仅在数据库完全启动时启动。但似乎并非如此。

【问题讨论】:

【参考方案1】:

将数据库容器指定为依赖项并不能保证它会在您的其他服务/容器之前准备好。它只保证它会在您的其他服务之前启动

解决此问题的一种方法是在启动期间无法连接到数据库时在 API 应用程序中实施重试尝试。

这是一篇使用 shell 脚本等待服务就绪的文章的link。

IMO 您的应用程序应该足够聪明,可以在无法建立数据库连接时重试几次。无论如何,它会使其更加健壮。

【讨论】:

这实际上并没有描述如何解决问题。提问者应该对其代码或容器环境进行哪些更改?

以上是关于无法从另一个容器连接到 Postgres 容器的主要内容,如果未能解决你的问题,请参考以下文章

无法从另一个容器连接到 mongodb docker 容器

无法从 golang 连接到 docker postgres 容器

在 Docker 容器中运行 .Net 5 API 时无法连接到 Postgres

允许 docker 容器连接到本地/主机 postgres 数据库

flyway 无法连接到 docker-entrypoint-initdb.d 脚本中的 postgres 容器

无法使用 docker 连接到 ipv6 中的 postgres