Go应用程序与Postgres之间的Docker组合通信问题

时间:2019-06-02 02:34:43

标签: postgresql docker go docker-compose

我正在尝试建立基本的Go应用程序以建立与Postgres数据库的连接。我俩都被使用docker-compose作为服务旋转了。当我运行docker-compose up时,当Go应用程序尝试连接到Postgres时,最终出现超时错误。某些错误或遗漏导致我的Go应用无法连接到Postgres。

docker-compose.yml

services:
  api:
    build: .
    ports:
      - 8080:8080
    environment:
      - GOPATH=/go # set up GOPATH in container to reference modules
      - DB_USERNAME=${DB_USERNAME}  # this is `postgres`
      - DB_PASSWORD=${DB_PASSWORD}  # this is an empty string
    volumes:
      - $GOPATH/pkg/mod:/go/pkg/mod

  db:
    image: postgres:11.3
    ports:
      - 5432:5432
    volumes:
      - ../db/postgres/data:/var/lib/postgresql/data

main.go

import (
    "database/sql"
    "log"

    "github.com/lib/pq"
)

func main() {
    dbConn, err := sql.Open("postgres", "sslmode=disable host=db port=5432 user=postgres dbname=postgres connect_timeout=30")
    if err != nil {
        log.Fatalf("error defining connection to database: %v", err)
    }
    defer func() { _ = dbConn.Close() }()

    // This forces the connection to be created
    err = dbConn.Ping()
    if err != nil {
        log.Fatalf("error opening connection to database: %v", err)
    }
    log.Println("Never get here because we timeout...")
}

我希望建立连接并到达main.go的结尾。相反,我收到以下错误:error opening connection to database: dial tcp <container-ip>:5432: i/o timeout

我尝试先启动Postgres容器(docker-compose up db),以确保它已经准备好,然后旋转我的Go应用程序(docker-compose up api)。同样的错误。

我已经登录到Postgres容器,并使用连接字符串手动连接到Postgres:psql "sslmode=disable host=localhost port=5432 user=postgres dbname=postgres connect_timeout=30"(注意,只有host字段从db更改为{{1 }},与上述localhost代码中使用的连接字符串相比)。可以,所以连接字符串就可以了。

登录到Postgres容器时,我已验证在连接字符串的main.go字段中使用了一个名为postgres的数据库:

dbname

我还尝试创建自己的数据库,并在连接字符串中使用它。

在上面的postgres=# \l List of databases Name | Owner | Encoding | Collate | Ctype | Access privileges -----------+----------+----------+------------+------------+----------------------- postgres | postgres | UTF8 | en_US.utf8 | en_US.utf8 | template0 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres + | | | | | postgres=CTc/postgres template1 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | =c/postgres + | | | | | postgres=CTc/postgres (3 rows) 代码中,我还尝试过将main.go行换成另一种方法:

sql.Open

如果我使用c, err := pq.NewConnector("sslmode=disable host=db port=5432 user=postgres dbname=postgres connect_timeout=30") dbConn = sql.OpenDB(c) (不在容器中运行)运行我的应用程序,并确保在Postgres连接字符串中将go run main.go切换为host,它将正常工作。因此,这与我的应用程序容器和Postgres容器之间的通信有关。

2 个答案:

答案 0 :(得分:0)

您的docker-compose.yml缺少指向db的链接,即它看起来像

services:
  api:
    build: .
    ports:
      - 8080:8080
    environment:
      - GOPATH=/go # set up GOPATH in container to reference modules
      - DB_USERNAME=${DB_USERNAME}  # this is `postgres`
      - DB_PASSWORD=${DB_PASSWORD}  # this is an empty string
    volumes:
      - $GOPATH/pkg/mod:/go/pkg/mod
    links:
      - db

  db:
    image: postgres:11.3
    ports:
      - 5432:5432
    volumes:
      - ../db/postgres/data:/var/lib/postgresql/data

答案 1 :(得分:0)

看看我的示例docker-compose文件(与mysql,postgres相同)

version: '3'
services:
  application:
    image: dangminhtruong/truyencotich:v1
    container_name: truyencotich
    ports:
    - 80:8080
    depends_on:
    - mysql
    volumes:
     - .:/app
    tty: true
    restart: always
    expose:
      - 8080
  mysql:
    image: mysql:5.7
    container_name: truyencotichDB
    environment:
      MYSQL_DATABASE: rivendell
      MYSQL_USER: truyencotich
      MYSQL_PASSWORD: 789852
      MYSQL_ROOT_PASSWORD: 789852
    volumes:
      - ./database/exported/exported.sql:/docker-entrypoint-initdb.d/rivendell.sql
    expose:
    - 3306
    ports:
    - 3306:3306

然后按以下方式连接(我们通过主机名连接到mysql db,现在是mysql容器名-truyencotichDB)

package database 

import (
    "database/sql"
    _ "github.com/go-sql-driver/mysql"
)

func DBConn() (db *sql.DB) {
    dbDriver := "mysql"
    dbUser := "root"
    dbPass := "789852"
    dbName := "rivendell"
    db, err := sql.Open(dbDriver, dbUser+":"+dbPass+"@tcp(truyencotichDB)/"+dbName)
    if err != nil {
        panic(err.Error())
    }