我正在尝试建立基本的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容器之间的通信有关。
答案 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())
}