Docker-сочинять проблемы связи между приложением Go и Postgres - PullRequest
0 голосов
/ 02 июня 2019

Я пытаюсь настроить основное приложение 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 на localhostпо сравнению со строкой соединения, использованной в коде main.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 (не работает в контейнере) и обязательно переключаю host на localhost в PostgresСтрока подключения, работает нормально.Так что это как-то связано с коммуникацией между контейнером моего приложения и контейнером Postgres.

Ответы [ 2 ]

0 голосов
/ 02 июня 2019

Посмотрите на мой пример docker-compose file (с mysql, postgres - то же самое)название контейнера - 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())
    }
0 голосов
/ 02 июня 2019

Ваш 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
...