简体   繁体   English

Docker构成Go应用程序和Postgres之间的通信问题

[英]Docker-compose communication issues between a Go app and Postgres

I'm trying to set up my basic Go app to make a connection to a Postgres database. 我正在尝试设置我的基本Go应用程序以建立与Postgres数据库的连接。 I have both being spun up as services using docker-compose. 我使用docker-compose作为服务进行了旋转。 When I run docker-compose up , I end up getting a timeout error when the Go app tries to connect to Postgres. 当我运行docker-compose up ,当Go应用程序尝试连接到Postgres时,我最终会收到超时错误。 Something is wrong or missing that is preventing my Go app from being able to make a connection to Postgres. 有些东西是错误的或遗漏的,这阻止了我的Go应用程序能够与Postgres建立连接。

docker-compose.yml 泊坞窗,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 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...")
}

I expect to make the connection and get to the end of main.go . 我期望建立连接并到达main.go Instead, I get the following error: error opening connection to database: dial tcp <container-ip>:5432: i/o timeout 相反,我收到以下错误: error opening connection to database: dial tcp <container-ip>:5432: i/o timeout

I've tried starting the Postgres container first ( docker-compose up db ), to make sure it was ready, then spinning up my Go app ( docker-compose up api ). 我已经尝试首先启动Postgres容器( docker-compose up db ),以确保它已准备好,然后启动我的Go应用程序( docker-compose up api )。 Same error. 同样的错误。

I've logged into the Postgres container and connected to Postgres by using the connection string, manually: psql "sslmode=disable host=localhost port=5432 user=postgres dbname=postgres connect_timeout=30" (notice that only the host field changed from db to localhost , as compared to the connection string used in the main.go code, above). 我已经登录到Postgres容器并通过连接字符串手动连接到Postgres: psql "sslmode=disable host=localhost port=5432 user=postgres dbname=postgres connect_timeout=30" (注意只有host字段从dblocalhost ,与上面main.go代码中使用的连接字符串相比。 This works, so the connection string is fine. 这有效,所以连接字符串很好。

When logged in to the Postgres container, I've verified that there is a database named postgres that I use in the dbname field in the connection string: 登录到Postgres容器后,我已经验证了在连接字符串的dbname字段中有一个名为postgres的数据库:

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)

I've also tried making my own database and using that in my connection string. 我也尝试创建自己的数据库并在我的连接字符串中使用它。

In the main.go code, above, I've also tried switching the sql.Open line out for the alternative approach: 在上面的main.go代码中,我也尝试将sql.Opensql.Open替代方法:

c, err := pq.NewConnector("sslmode=disable host=db port=5432 user=postgres dbname=postgres connect_timeout=30")
dbConn = sql.OpenDB(c)

If I run my app with go run main.go (not running in a container) and make sure to switch the host to localhost in the Postgres connection string, it works fine. 如果我使用go run main.go运行我的应用程序(不在容器中运行)并确保将host切换到Postgres连接字符串中的localhost ,它可以正常工作。 So, it's something to do with the communication between my app's container and the Postgres container. 所以,这与我的应用程序容器和Postgres容器之间的通信有关。

Your docker-compose.yml misses a link to db , ie, it should look like 你的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

Take a look to my example docker-compose file (with mysql, postgres is the same way) 看看我的示例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

And then I connect by following (we connect to mysql db by host name now is mysql container name - truyencotichDB) 然后我通过以下连接(我们通过主机名连接到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())
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM