【问题标题】:How connect to postgres from a golang app when using docker-compose?使用 docker-compose 时如何从 golang 应用程序连接到 postgres?
【发布时间】:2018-03-18 01:02:50
【问题描述】:

我的 docker-compose 文件

version: "2" 
services:   db:
   restart: always
   image: postgres:latest
   ports:
     - "5435:5432"
   environment:
      POSTGRES_PASSWORD: password
      POSTGRES_USER: user
      POSTGRES_DB: db   adminer:    
   web:
      image: golang:1.7
      working_dir: /go/src/app
      command: go run bot.go
      ports:
        - "3000:3000"
      volumes:
        - ./bot:/go/src/app
      links:
        - db
      environment:
      PORT: 3000
      CONNECTION_STRING_DEV: postgres://user:password@db/db

还有我的 bot.go,我在这里尝试连接

db, err = sql.Open("postgres", "user=user password=password host=db dbname=db port=5432 sslmode=verify-full ")

当我打开我的容器时,我看到了错误:

panic: dial tcp 5.61.14.99:5432: getsockopt: connection refused

我更改了 5432 上的端口并尝试像这样连接:

db, err = sql.Open("postgres", "postgres://user:password@db/db")

但我得到了同样的错误

我的 docker-compose 设置有什么问题?

【问题讨论】:

  • 谢谢,我在 bot.go 中更改了代码,使用了 os.Getenv("CONNECTION_STRING_DEV"),但它并没有解决我的问题
  • os.Getenv("CONNECTION_STRING_DEV") 的值是多少?
  • 你试过不使用 ssl 吗? postgres://user:password@db/db?sslmode=disableuser=user password=password host=db dbname=db port=5432 sslmode=disable.
  • 是的,我试过了。我想,我尝试了所有变体))
  • 我认为你需要一座桥? stackoverflow.com/questions/43754095/…

标签: postgresql go docker-compose


【解决方案1】:

您的 docker-compose 看起来有点乱,但这可能是复制和粘贴造成的。当 Go 尝试连接时,postgres 可能尚未启动并运行。要测试这是否是问题所在,首先:

docker-compose up -d db

然后通过检查等到 postgres 准备好:

docker-compose logs -f db

并注意以下日志行:

db_1   | LOG:  database system is ready to accept connections

当该行出现时,退出日志命令 (Ctrl+C) 并运行您的机器人:

docker-compose up web

如果它现在可以工作,那确实是你的问题。

解决方案:等到 postgres 准备好。实现这一目标的简单方法是:

  • 在运行 web 之前睡眠一段时间(例如 1 分钟)
  • 在连接之前先在网络中休眠
  • 连接失败时,休眠 5 秒后无限期重试

这些的缺点是你不知道 postgres 什么时候准备好,所以你可能等待太久或不够长。更好的解决方案是仅在成功连接到 postgres 后运行您的机器人。

来自https://docs.docker.com/compose/startup-order/的示例:

#!/bin/bash
# wait-for-postgres.sh

set -e

host="$1"
shift
cmd="$@"

until psql -h "$host" -U "postgres" -c '\l'; do
  >&2 echo "Postgres is unavailable - sleeping"
  sleep 1
done

>&2 echo "Postgres is up - executing command"
exec $cmd

将此脚本添加为 wait-for-postgres.sh 并在 docker-compose.yml 中更改 web 的命令,如下所示:

command: ["./wait-for-postgres.sh", "db", "go", "run", "bot.go"]

【讨论】:

  • 谢谢你,这个答案很好,我明白如何测试我的容器。我运行“db”容器,然后运行容器“web”,但看到同样的错误,然后我添加了代码超时,但它不起作用。所以可能是 pg_hba.conf 出错了?
  • 运行db后,是否等待postgres准备好?我不认为这是配置问题,因为错误消息表明存在较低级别的问题。
  • 是的,日志:数据库系统已准备好接受连接,如果我运行 sudo docker-compose ps,我看到 docker-entrypoint.sh postgres Up 0.0.0.0:5432->5432/tcp跨度>
  • 但是当我运行 sudo docker-compose up web 时,我看到: panic: dial tcp 5.61.14.99:5432: getsockopt: connection denied
  • 在 postgres 映像上未启用 SSL。我可以使用 sql.Open(),但要对数据库进行实际操作,我必须使用 `db, err := sql.Open("postgres", "postgres://user:password@db/db?sslmode=禁用")`。
【解决方案2】:

我找到了答案,我已经在其他应用程序中运行了带有 postgres 的容器,我没有考虑这一点,因为 docker compose 在构建 db 容器时没有显示错误。我使用docker ps 然后docker stop xxxxx 并从其他应用程序中停止数据库容器,然后构建和构建我的应用程序,问题就解决了。

【讨论】:

    猜你喜欢
    • 2021-07-14
    • 2019-07-30
    • 1970-01-01
    • 1970-01-01
    • 2019-04-22
    • 1970-01-01
    • 2020-02-19
    • 2016-12-27
    • 1970-01-01
    相关资源
    最近更新 更多