【问题标题】:How to make connection between Docker Containers如何在 Docker 容器之间建立连接
【发布时间】:2018-12-11 21:19:47
【问题描述】:

当我尝试将我的 goLang GORM 服务连接到 Docker Postgress 容器时遇到连接问题。我相信问题是我在连接字符串底部的 golang 代码。

docker-compose up
Recreating postgress_postgre_1 ... done
Attaching to postgres
postgres   | 2018-12-11 21:08:48.283 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
postgres   | 2018-12-11 21:08:48.283 UTC [1] LOG:  listening on IPv6 address "::", port 5432
postgres   | 2018-12-11 21:08:48.291 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
postgres   | 2018-12-11 21:08:48.316 UTC [20] LOG:  database system was shut down at 2018-12-11 21:08:44 UTC
postgres   | 2018-12-11 21:08:48.328 UTC [1] LOG:  database system is ready to accept connections

=== 当我运行 golang 时,我得到...恐慌:无法连接数据库

=============== docker-compose.yml

version: '3.6'
services:
  postgre:
    image: postgres:11.1-alpine
    ports:
      - '5432:5432'
    network_mode: bridge
    container_name: postgres

    environment:
      POSTGRES_USER: 'user'
      POSTGRES_PASSWORD: 'password'
      POSTGRESS_DB: 'db_amex01'
    volumes:
      - ./init:/docker-entrypoint-initdb.d/

==== main.go

主包

import (
    "fmt"
    "log"
    "net/http"

    "github.com/gorilla/mux"
    "github.com/jinzhu/gorm"

    // _ "github.com/jinzhu/gorm/dialects/sqlite"
    _ "github.com/jinzhu/gorm/dialects/postgres"
)

// _ "github.com/jinzhu/gorm/blob/master/dialects/postgres"

type ToDo struct {
    gorm.Model
    ID          int    `json:"id"`
    TASK_STRING string `json:"task_string"`
    DONE        bool   `json:"done"`
}

var db *gorm.DB
var err error

func main() {
    const (
        host     = "localhost"
        port     = 5432
        user     = "postgres"
        password = "password"
        dbname   = "db_amex01"
    )


// this is the problem I believe I am having...

    db, err := gorm.Open("postgres", "host='postgres' port=5432 user=user dbname='db_amex01' password='password'")



    defer db.Close()

    if err != nil {
        panic("failed to connect database")
    }

    defer db.Close()

【问题讨论】:

  • 你在 docker 之外运行你的 go 程序吗?您是否尝试将主机从postgres 更改为localhostpostgre?你用的是什么系统?

标签: postgresql go docker-compose go-gorm


【解决方案1】:

您的撰写文件中有一个错字,您将服务命名为 postgre 但连接到 postgres。 Docker 使用共享网络上的 DNS 别名的服务名称,因此这会中断您的连接尝试。要修复,只需重命名您的服务:

version: '3.6'
services:
  postgres:
    image: postgres:11.1-alpine
    ports:
      - '5432:5432'
    environment:
      POSTGRES_USER: 'user'
      POSTGRES_PASSWORD: 'password'
      POSTGRESS_DB: 'db_amex01'
    volumes:
      - ./init:/docker-entrypoint-initdb.d/

【讨论】:

    【解决方案2】:

    您似乎正在丢弃从gorm.Open() 返回的错误。要确切知道 gorm 无法打开连接的原因,您需要输出错误。

    代替:

    panic("failed to connect database")
    

    用途:

    panic("failed to connect database: " + err)
    

    乍一看,可能是您的主机配置错误

    host='postgres' port=5432 user=user dbname='db_amex01' password='password'
    

    应该是:

    host=localhost port=5432 user=user dbname=db_amex01 password=password
    

    但如果没有来自gorm.Open() 的错误,就很难判断

    还有一点需要注意;在第一次检查错误之前不要打电话给db.Close()。在出现错误的情况下,db 可能是 nil,从而导致对 db 的任何方法的调用出现恐慌。您还在您发布的代码 sn-p 中调用了两次db.Close()。不要这样做。 Golang 在io.Closer 上的文档:

    Closer 是封装了基本 Close 方法的接口。

    第一次调用后关闭的行为未定义。具体的 实现可以记录他们自己的行为。

    编辑(2018 年 12 月 12 日):

    当我在本地运行您的代码时,我从 gorm 得到的错误是关于 SSL,因为您正在通过 docker-compose 运行您的 postgres 服务器,而没有任何 SSL 配置。您可以将sslmode=disable 标志添加到您的连接字符串以解决此问题。

    您的docker-compose.yml 中还有一个错字:POSTGRESS_DB 应该是POSTGRES_DB

    这是我在本地运行的完整工作示例:

    docker-compose.yml:

    version: '3.6'
    services:
      postgres:
        image: postgres:11.1-alpine
        ports:
          - '5432:5432'
        environment:
          POSTGRES_USER: 'test_user'
          POSTGRES_PASSWORD: 'test_password'
          POSTGRES_DB: 'test_database'
        volumes:
          - ./init:/docker-entrypoint-initdb.d/
    

    main.go:

    package main
    
    import (
        "fmt"
        "log"
    
        "github.com/jinzhu/gorm"
        _ "github.com/jinzhu/gorm/dialects/postgres"
    )
    
    const (
        host     = "localhost"
        port     = "5432"
        user     = "test_user"
        password = "test_password"
        dbname   = "test_database"
    )
    
    func main() {
        url := fmt.Sprintf("postgres://%s:%s@%s:%s/%s?sslmode=disable",
            user,
            password,
            host,
            port,
            dbname,
        )
    
        db, err := gorm.Open("postgres", url)
        if err != nil {
            log.Fatalf("error connecting to database: %v", err)
        }
        defer db.Close()
    
        if err := db.DB().Ping(); err != nil {
            log.Fatalf("error pinging database: %v", err)
        }
    
        fmt.Println("Success!")
    }
    

    【讨论】:

    • 在 Docker 上下文中 localhost 几乎总是错误的。您可能需要postgre,即docker-compose.yml 文件中另一个服务器块的名称;它将作为主机名解析为另一个容器的私有 IP 地址。
    • 当我尝试从 docker 容器外部建立连接时,我使用的是本地主机。我尝试了很多组合,并用最新的代码更新了我的 github 页面......以及问题描述。我还包括连接错误。
    • @IrishGringo 我已经更新了我的答案以包含正确的解决方案。
    猜你喜欢
    • 2019-02-19
    • 2023-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多