如何在 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/
当我尝试将我的 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/