如何在 Docker 个容器之间建立连接

How to make connection between Docker Containers

当我尝试将我的 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()

您似乎正在放弃从 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 的任何方法的调用出现恐慌。您还在发布的代码片段中两次调用 db.Close() 。不要这样做。 Golang 关于 io.Closer 的文档:

Closer is the interface that wraps the basic Close method.

The behavior of Close after the first call is undefined. Specific implementations may document their own behavior.

编辑(2018 年 12 月 12 日):

当我在本地 运行 你的代码时,我从 gorm 得到的错误是关于 SSL 的,因为你是 运行 你的 postgres 服务器,通过 docker-compose 没有任何 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!")
}

您的撰写文件中有错字,您将服务命名为 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/