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

时间:2017-10-06 09:00:17

标签: 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

和我的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设置出了什么问题?

2 个答案:

答案 0 :(得分:4)

你的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准备就绪。实现这一目标的简便方法是:

  • 在运行网络之前睡了一段时间(例如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"]

答案 1 :(得分:0)

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