首页 > 解决方案 > Go 应用程序和 Postgres 之间的 Docker-compose 通信问题

问题描述

我正在尝试设置我的基本 Go 应用程序以连接到 Postgres 数据库。我都使用 docker-compose 作为服务启动。当我运行docker-compose up时,当 Go 应用程序尝试连接到 Postgres 时,我最终会收到超时错误。某些错误或缺失导致我的 Go 应用程序无法连接到 Postgres。

码头工人-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为)。这行得通,所以连接字符串很好。localhostmain.go

登录到 Postgres 容器时,我已验证在连接字符串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)

如果我使用(不在容器中运行)运行我的应用程序go run main.go并确保在 Postgres 连接字符串中切换host到,它可以正常工作。localhost因此,这与我的应用程序容器和 Postgres 容器之间的通信有关。

标签: postgresqldockergodocker-compose

解决方案


看一下我的示例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())
    }

推荐阅读