Go容器无法连接Postgres-alpine容器问题求助
问题详情
尝试将Go容器与postgres-alpine容器建立连接时失败,报错如下:
web_1 | [error] failed to initialize database, got error failed to connect to
host=db user=postgres database=go: dial error (dial tcp 192.168.144.2:5432: connect: no route
to host)
web_1 | 2023/09/05 09:26:10 Failed to connect to database:
web_1 | failed to connect tohost=db user=postgres database=go: dial error (dial tcp
192.168.144.2:5432: connect: no route to host)
使用.air.toml运行服务器,相关配置及代码如下:
docker-compose.yml
version: '3.7' services: db : image : postgres:alpine environment: - POSTGRES_USER=${DB_USER} - POSTGRES_PASSWORD=${DB_PASSWORD} - POSTGRES_DB=${DB_NAME} ports : - 5432:5432 volumes: - postgres-db:/var/lib/postgresql/data web : build : . env_file : - .env ports : - 3000:3000 depends_on : - db volumes : - .:/usr/src/app command : air cmd/main.go -b 0.0.0.0 volumes: postgres-db:
数据库连接函数代码
func ConnectDb() { dsn := fmt.Sprintf("host=db user=%s password=%s dbname=%s port=5432 sslmode=disable TimeZone=Asia/India", os.Getenv("DB_USER"), os.Getenv("DB_PASSWORD"), os.Getenv("DB_NAME"), ) db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{ Logger: logger.Default.LogMode(logger.Info), }) if err != nil { log.Fatal("Failed to connect to database: ", err) os.Exit(2) } log.Println("connected") db.Logger = logger.Default.LogMode(logger.Info) log.Println("running migrations") db.AutoMigrate(&models.Facts{}) DB = Dbinstance{ Db: db, } }
.env文件内容
DB_USER=postgres DB_PASSWORD=root DB_NAME=go
解决方案
1. 处理Postgres服务就绪延迟
depends_on仅保证db容器先启动,但Postgres服务可能还未完成初始化。可以通过两种方式解决:
方式一:添加启动等待脚本
修改docker-compose.yml中web服务的command,使用脚本等待Postgres端口就绪:
command: sh -c "wget -qO- https://raw.githubusercontent.com/vishnubob/wait-for-it/master/wait-for-it.sh | sh -s -- db:5432 -t 30 -- air cmd/main.go -b 0.0.0.0"
方式二:在Go代码中添加重试逻辑
修改ConnectDb函数,增加连接重试机制:
import "time" func ConnectDb() { var db *gorm.DB var err error maxRetries := 5 retryDelay := 2 * time.Second for i := 0; i < maxRetries; i++ { dsn := fmt.Sprintf("host=db user=%s password=%s dbname=%s port=5432 sslmode=disable TimeZone=Asia/India", os.Getenv("DB_USER"), os.Getenv("DB_PASSWORD"), os.Getenv("DB_NAME"), ) db, err = gorm.Open(postgres.Open(dsn), &gorm.Config{ Logger: logger.Default.LogMode(logger.Info), }) if err == nil { break } log.Printf("连接失败,%v后重试... (第%d/%d次尝试)", retryDelay, i+1, maxRetries) time.Sleep(retryDelay) } if err != nil { log.Fatal("多次尝试后仍无法连接数据库: ", err) os.Exit(2) } log.Println("连接成功") db.Logger = logger.Default.LogMode(logger.Info) log.Println("执行迁移") db.AutoMigrate(&models.Facts{}) DB = Dbinstance{Db: db} }
2. 验证Docker网络一致性
docker-compose默认会为服务创建专属网络,检查两个容器是否在同一网络:
docker inspect $(docker-compose ps -q web) | grep Networks docker inspect $(docker-compose ps -q db) | grep Networks
若不在同一网络,删除现有容器和卷后重新构建:
docker-compose down -v docker-compose up --build
3. 检查Postgres容器运行状态
查看Postgres容器日志,确认服务是否正常初始化:
docker-compose logs db
若日志显示权限等初始化错误,删除postgres-db卷后重新启动:
docker-compose down -v docker-compose up
内容的提问来源于stack exchange,提问作者Venukishore.R

