You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Gorm连接Docker部署的PostgreSQL时遇连接拒绝错误求助

PostgreSQL与Gorm连接问题解决

问题概述

尝试通过Docker Compose部署的PostgreSQL数据库,使用Gorm进行Go语言连接时出现连接拒绝错误,同时本地用DBeaver连接也失败。

Docker Compose配置

services:
  app:
    build: 
      context: .
      # Correct the path to your Dockerfile
      dockerfile: Dockerfile
    ports:
      - "127.0.0.1:8080:8080"
    volumes:
      - .:/app
    networks:
      - backend
    depends_on:
      - db
  
  db:
    container_name: simple_api_db_user
    restart: always
    image: postgres:latest
    environment:
      POSTGRES_USER: mateen
      POSTGRES_PASSWORD: password
      POSTGRES_DB: simple_api_db_user
    volumes:
      - db_data:/var/lib/postgresql/data
    networks:
      - backend
    ports:
      - "127.0.0.1:5430:5430"
  
volumes:
  db_data:

networks:
  backend:
    driver: bridge

Go语言连接代码

func NewPostgresConnection() (*gorm.DB, error) {
    psqlConfig, err := dbConfigs.NewPostgresqlConfig()
    if err != nil {
        return nil, err
    }

    db, err := sql.Open("postgres", psqlConfig.Dsn())
    if err != nil {
        log.Println("DB Connection error : ", err.Error())
        return nil, err
    }

    if err := db.Ping(); err != nil {
        log.Println("DB Ping error: ", err.Error())
        return nil, err
    }

    gdb, err := gorm.Open(postgres.Open(psqlConfig.Dsn()), &gorm.Config{})
    if err != nil {
        return nil, err
    }

    err = Migrate(gdb)
    if err != nil {
        return nil, err
    }

    return gdb, nil
}

DSN配置与错误信息

打印的DSN配置:
&{host=simple_api_db_user user=mateen password=password dbname=simple_api_db_user port=5430 sslmode=disable TimeZone=UTC}

应用运行错误:

simple-api-user-app-1  | 2023/05/10 14:05:16 DB Ping error:  dial tcp 172.31.0.2:5430: connect: connection refused
simple-api-user-app-1  | 2023/05/10 14:05:16 dial tcp 172.31.0.2:5430: connect: connection refused

DBeaver连接错误:

The connection attempt failed.
  EOFException
  java.io.EOFException

Dockerfile内容

# Builder
FROM golang:latest

WORKDIR /app

COPY go.mod go.sum ./

RUN go mod download

RUN go install github.com/cosmtrek/air@latest

COPY . .

CMD [ "air" ]

EXPOSE 8080

解决方案

1. 修正PostgreSQL容器端口映射

PostgreSQL默认监听端口是5432,你的Docker Compose中把主机5430端口映射到容器的5430端口,但容器内Postgres并未在5430端口运行,这是核心问题。修改db服务的ports配置:

ports:
  - "127.0.0.1:5430:5432"

这样主机5430端口会转发到容器内的5432端口,本地工具(如DBeaver)就能通过5430连接数据库。

2. 调整容器内连接端口

因为Go应用和PostgreSQL容器在同一个Docker网络(backend)内,应用连接数据库时应该使用容器内部的默认端口5432,而不是5430。修改你的DSN配置,将port改为5432:
&{host=simple_api_db_user user=mateen password=password dbname=simple_api_db_user port=5432 sslmode=disable TimeZone=UTC}

3. 优化数据库连接时机(可选)

depends_on仅保证容器启动顺序,不确保PostgreSQL服务完全就绪。可以在Go代码中添加连接重试逻辑,避免数据库未初始化完成就尝试连接:

import "time"

func NewPostgresConnection() (*gorm.DB, error) {
    psqlConfig, err := dbConfigs.NewPostgresqlConfig()
    if err != nil {
        return nil, err
    }

    var db *sql.DB
    var pingErr error
    // 最多重试5次,每次间隔2秒
    for i := 0; i < 5; i++ {
        db, err = sql.Open("postgres", psqlConfig.Dsn())
        if err != nil {
            log.Println("DB Connection error : ", err.Error())
            time.Sleep(2 * time.Second)
            continue
        }
        pingErr = db.Ping()
        if pingErr == nil {
            break
        }
        log.Println("DB Ping error, retrying...: ", pingErr.Error())
        time.Sleep(2 * time.Second)
    }
    if pingErr != nil {
        return nil, pingErr
    }

    gdb, err := gorm.Open(postgres.Open(psqlConfig.Dsn()), &gorm.Config{})
    if err != nil {
        return nil, err
    }

    err = Migrate(gdb)
    if err != nil {
        return nil, err
    }

    return gdb, nil
}

4. 验证修改

  • 重启Docker Compose服务:docker-compose down && docker-compose up -d
  • 用DBeaver连接localhost:5430,使用配置的用户名、密码和数据库名,验证连接是否正常
  • 启动Go应用,检查是否还存在连接拒绝错误

内容的提问来源于stack exchange,提问作者Mateen Bagheri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 13:32:03