Docker Compose下Golang API无法连接PostgreSQL求助
问题分析
从日志时间线可明确问题根源:
- Go服务在
22:51:23尝试连接PostgreSQL,但PostgreSQL在22:51:24才开始监听端口,此时数据库尚未就绪,导致连接被拒绝。 - 重启容器时PostgreSQL已处于运行就绪状态,因此Go服务能正常连接。
解决方案
1. 配置Docker Compose依赖与健康检查
默认的depends_on仅保证容器启动顺序,无法确保服务就绪。需给PostgreSQL添加健康检查,让Go服务等待数据库完全就绪后再启动:
修改docker-compose.yml:
version: "3.7" services: gobank: build: . container_name: gobank env_file: - .env ports: - 3000:3000 command: make run extra_hosts: - "host.docker.internal:host-gateway" depends_on: db: condition: service_healthy # 等待db健康检查通过 db: image: postgres:16 container_name: postgres environment: - POSTGRES_PASSWORD=postgres - POSTGRES_USER=postgres - POSTGRES_DB=gobank ports: - 5432:5432 extra_hosts: - "host.docker.internal:host-gateway" healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres -d gobank"] interval: 2s timeout: 5s retries: 5 # 最多重试5次,每次间隔2秒
2. 在Go代码中添加连接重试逻辑
即使配置了Docker健康检查,仍可能存在网络波动或服务启动延迟,在代码层面添加重连逻辑可彻底规避此类问题:
示例代码:
import ( "database/sql" "fmt" "time" _ "github.com/lib/pq" ) func connectDB(user, dbname, password string) (*sql.DB, error) { connStr := fmt.Sprintf("host=db port=5432 user=%s dbname=%s password=%s sslmode=disable", user, dbname, password) var db *sql.DB var err error // 最多重试5次,每次间隔3秒 for i := 0; i < 5; i++ { db, err = sql.Open("postgres", connStr) if err == nil { // 验证连接是否有效 if err = db.Ping(); err == nil { break } } fmt.Printf("连接数据库失败,%d秒后重试...\n", 3) time.Sleep(3 * time.Second) } return db, err }
3. 临时方案:手动控制启动顺序
若不想修改配置和代码,可先单独启动PostgreSQL容器,确认其就绪后再启动Go服务:
# 先启动db服务 docker-compose up -d db # 等待几秒确认数据库就绪后,启动gobank docker-compose up gobank
内容的提问来源于stack exchange,提问作者Leonardo Alipazaga Bazan
相关产品推荐
相关产品推荐

