使用 docker-compose 时如何从 golang 应用程序连接到 postgres?

Con*_*olt 2 postgresql go docker-compose

我的 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
Run Code Online (Sandbox Code Playgroud)

和我的 bot.go,我尝试连接的地方

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

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

panic: dial tcp 5.61.14.99:5432: getsockopt: connection refused
Run Code Online (Sandbox Code Playgroud)

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

db, err = sql.Open("postgres", "postgres://user:password@db/db")
Run Code Online (Sandbox Code Playgroud)

但我得到了同样的错误

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

小智 6

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

docker-compose up -d db
Run Code Online (Sandbox Code Playgroud)

然后通过检查等待 postgres 准备就绪:

docker-compose logs -f db
Run Code Online (Sandbox Code Playgroud)

并注意以下日志行:

db_1   | LOG:  database system is ready to accept connections
Run Code Online (Sandbox Code Playgroud)

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

docker-compose up web
Run Code Online (Sandbox Code Playgroud)

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

解决方案:等到 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
Run Code Online (Sandbox Code Playgroud)

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

command: ["./wait-for-postgres.sh", "db", "go", "run", "bot.go"]
Run Code Online (Sandbox Code Playgroud)