我从Docker中的Go应用收到以下错误消息:
panic: failed to connect to `host=localhost user=postgres-dev database=dev`: dial error (dial tcp [::1]:5432: connect: cannot assign requested address)
出现在下一个Dockerfile
和docker-compose.yml
文件的环境中:
FROM golang:latest
WORKDIR /WD
COPY go.mod go.sum ./
RUN go mod download
COPY . .
docker-compose.yml
文件:
version: '3'
services:
db:
image: postgres:latest
environment:
POSTGRES_DB: dev
POSTGRES_USER: postgres-dev
POSTGRES_PASSWORD: [~secret~]
ports: 5432:5432
app:
build: .
command: ["./wait-for-it.sh", "db:5432", "--", "go", "run", "main.go"]
volumes:
- .:/WD
ports:
- "8000:8000"
depends_on:
- db
links:
- db
此处是main.go
文件:
package main
import (
"context"
"fmt"
"log"
"net/http"
api "github.com/[placeholder]/[placeholder]/api"
db "github.com/[placeholder]/[placeholder]/db"
pgx "github.com/jackc/pgx/v4"
)
func main() {
fmt.Println("Init")
r := api.InitRoutes()
conn, err := pgx.Connect(context.Background(), "postgresql://postgres-dev:[~secret~]@localhost:5432/dev")
if err != nil {
panic(err) // the error appears from this line.
}
dbInstance := &db.DbService{Conn: conn}
dbInstance.Conn.Ping(context.Background())
dbInstance.Migrate("/db/db.sql")
http.ListenAndServe(":8000", r)
}
在控制台日志中,我找到了与该问题有关的下几行:
db_1 | 2019-12-07 08:08:59.350 UTC [1] LOG: starting PostgreSQL 12.1 (Debian 12.1-1.pgdg100+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit
db_1 | 2019-12-07 08:08:59.351 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432
# read the next line:
db_1 | 2019-12-07 08:08:59.351 UTC [1] LOG: listening on IPv6 address "::", port 5432
数据库的地址为:: with port 5432
,而程序尝试连接到::1 with port 5432
时,这可能是问题的原因吗?
答案 0 :(得分:0)
在附着到bridge network(默认)localhost
(127.0.0.1)的容器中是容器本身。因此,您的app
容器正尝试通过自身(而不是主机或db
容器上的端口5432)访问数据库。最简单的解决方法是将连接字符串更改为:
postgresql://postgres-dev:[~secret~]@localhost:5432/dev
到
postgresql://postgres-dev:[~secret~]@db:5432/dev
注意:我认为您的docker-compose.yml
中有一个错字-ports: 5432:5432
设置了一个环境变量而不是映射端口(请注意,app
实际上不需要这么做(默认情况下,它们都位于同一bridged network上,则转到db
)。
注意2:在这种情况下,您无需使用links(这是一项旧功能)。