【发布时间】:2020-11-14 08:29:07
【问题描述】:
我目前在我的 PC 上设置了两个 docker 容器,其中一个是使用 docker compose 创建的 PostgreSQL 容器,另一个包含用于初始化 PostgreSQL 数据库中的表的 go 代码。 Docker compose 在创建容器/数据库方面非常有效(我将通过容器外部的 psql 登录它),并且 go 代码本身在容器外部正常运行(创建表)。当我尝试从其自己的容器内运行代码时,无论我尝试连接到本地数据库还是容器化数据库,都会出现问题。这两种情况都会导致标题中的拨号错误。
我只是 docker 的初学者,所以我知道这很可能是我的问题,但这里是我的 dockerfile 的内容:
FROM golang:alpine AS builder
#adding needed env variables
ENV GO111MODULE=on \
CGO_ENABLED=0 \
GOOS=linux \
GOARCH=amd64
#move to /build
WORKDIR /build
#copy dependancies
COPY go.mod .
COPY go.sum .
RUN go mod download
#add code to container
COPY . .
#build app
RUN go build -o main .
# Move to /dist directory as the place for resulting binary folder
WORKDIR /dist
# Copy binary from build to main folder
RUN cp /build/main .
# Build a small image
FROM scratch
COPY --from=builder /dist/main /
ENV DATABASE_URL=postgres://short:password@test:8001/shorturl
#change database url variable to match your needs
# Command to run
ENTRYPOINT ["/main"]
以及 docker-compose.yml 文件的内容:
version: '3'
services:
database:
container_name: test
image: "postgres" # use latest official postgres version
env_file:
- ./db/database.env # configure postgres
volumes:
- database-data:/var/lib/postgresql/data/ # persist data even if container shuts down
ports:
- "8001:5432"
backend:
build: .
volumes:
database-data:
代码本身存在于以下目录结构中:
/project/
./db/
db.go
database.env
main.go
go.mod
go.sum
Dockerfile
docker-compose.yml
db.go 包含:
package db
import (
"context"
"fmt"
"os"
"github.com/jackc/pgx/v4/pgxpool"
)
//InitDb creates a connection to our postgres db and populates it
func InitDb(dbURL string) *pgxpool.Pool {
connPool, err := pgxpool.Connect(context.Background(), dbURL)
if err != nil {
fmt.Fprintf(os.Stderr, "Unable to connect to database: %v\n", err)
os.Exit(1)
}
return connPool
}
//PopulateDb populates our databse with the appropiate tables i.e id, url, base64 encoding, visited, visit count
func PopulateDb(db *pgxpool.Pool) {
_, err := db.Exec(context.Background(), "create table if not exists shortener (id serial primary key not null, url varchar not null, visited boolean default false, count integer default 0);")
if err != nil {
fmt.Fprintf(os.Stderr, "Unable to create users table: %v\n", err)
os.Exit(1)
}
fmt.Printf("Successfully created users table\n")
}
database.env 用于使用 docker-compose 生成数据库包含:
POSTGRES_USER=short
POSTGRES_PASSWORD=password
POSTGRES_DB=shorturl
main.go 包含:
package main
import (
"fmt"
"os"
"project/db"
)
func main() {
/*
set databse url in this format from root directory
DATABASE_URL=postgres://user:password@host:port/database
*/
dbURL := os.Getenv("DATABASE_URL")
conn := db.InitDb(dbURL)
db.PopulateDb(conn)
defer conn.Close()
}
正如我之前提到的,在任何容器之外运行所有这些工作并填充数据库,并且 docker-compose 成功创建了一个我可以在本地连接到的 postgres 实例。
我不能做的是通过我的代码(在本地或在容器中运行)连接到容器化的 postgres,或者从我的代码的容器化版本连接到本地数据库。所有这些都会导致此错误的一些变化:
Unable to connect to database: failed to connect to `host=container_name user=short database=shorturl`: dial error (dial tcp 172.18.0.2:8001: connect: connection refused)
我很好奇我的代码和/或 docker 可能做错了什么,并希望有人可以最终运行它并重现我的问题/找出问题所在。
【问题讨论】:
-
尝试使用 5432 更改配置端口。
DATABASE_URL=postgres://short:password@test:5432/shorturl。使用8001只能从 docker-compose 外部访问。 docker-compose 服务内部的互通容器应该通过它们的默认端口工作。
标签: postgresql docker go tcp docker-compose