Я пытаюсь настроить основное приложение 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.