Golang+Postgres+Docker部署:Dial tcp连接拒绝问题求助
使用Docker Compose部署Golang+Postgres时连接被拒绝的解决方案
问题分析
报错Dial tcp 172.18.0.2:5432: connect: connection refused的核心原因:
depends_on仅保证容器启动顺序,不确保Postgres服务完全就绪- 即使配置了healthcheck,默认情况下Golang应用容器不会等待数据库容器的健康检查通过就启动
修复步骤
1. 修改Docker Compose配置,让应用等待数据库就绪
更新docker-compose.yml中balance-app的depends_on配置,添加健康检查依赖条件:
version: '3.8' services: balance-app: build: ./ command: ./balance-app ports: - 8000:8000 depends_on: db: condition: service_healthy # 等待db容器健康检查通过 environment: - DB_PASSWORD=qwerty - DB_HOST=db db: restart: always image: postgres:latest volumes: - ./.database/postgres/data:/var/lib/postgresql/data environment: - POSTGRES_PASSWORD=qwerty ports: - 5432 healthcheck: test: [ "CMD-SHELL", "pg_isready -U postgres" ] interval: 3s timeout: 5s retries: 5 # 增加重试次数,确保数据库完全启动
2. 验证Golang配置加载逻辑
确保Viper正确读取配置文件,在数据库初始化代码前添加配置加载逻辑(如果未添加):
import ( "log" "github.com/spf13/viper" ) func init() { // 设置配置文件路径和格式 viper.AddConfigPath(".") viper.SetConfigName("config") viper.SetConfigType("yaml") if err := viper.ReadInConfig(); err != nil { log.Fatalf("Failed to load config: %v", err) } }
另外,检查数据库端口是否需要转换为整数(部分Postgres驱动要求端口为int类型):
import "strconv" // ... portStr := viper.GetString("db.port") port, err := strconv.Atoi(portStr) if err != nil { log.Fatalf("Invalid DB port: %v", err) } db, err := repository.NewPostgresDB(repository.Config{ Host: os.Getenv("DB_HOST"), Port: port, // 使用int类型端口 Username: viper.GetString("db.username"), DBName: viper.GetString("db.dbname"), SSLMode: viper.GetString("db.sslmode"), Password: os.Getenv("DB_PASSWORD"), })
3. 添加数据库连接重试逻辑
在应用初始化时添加重试机制,应对偶发的启动延迟:
import ( "log" "time" ) func main() { var db *sql.DB var err error maxRetries := 5 for i := 0; i < maxRetries; i++ { db, err = repository.NewPostgresDB(repository.Config{ Host: os.Getenv("DB_HOST"), Port: viper.GetString("db.port"), Username: viper.GetString("db.username"), DBName: viper.GetString("db.dbname"), SSLMode: viper.GetString("db.sslmode"), Password: os.Getenv("DB_PASSWORD"), }) if err == nil { log.Println("Successfully connected to database") break } log.Printf("Connection attempt %d failed: %v. Retrying in 2s...", i+1, err) time.Sleep(2 * time.Second) } if err != nil { log.Fatalf("Failed to connect to database after %d retries: %v", maxRetries, err) } // 后续应用逻辑... }
4. 验证数据库容器状态
运行以下命令检查数据库容器的健康状态:
docker-compose ps
确保db容器的状态为healthy。也可以查看日志确认健康检查是否正常:
docker-compose logs db
内容的提问来源于stack exchange,提问作者mbesan
相关产品推荐
相关产品推荐

