postgresql - 尝试在一个连接到另一个容器中的postgres的容器中运行go程序时发生拨号错误(拨号tcp 172.18.0.2:8001:connect:连接被拒绝)

标签 postgresql docker go tcp docker-compose

我目前在我的PC上设置了两个docker容器,其中一个是使用docker compose创建的PostgreSQL容器,另一个是包含go代码以初始化PostgreSQL数据库中的表。 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")
}
用于通过docker-compose生成数据库的database.env包含:
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中可能做错了什么,希望有人可以在其末端运行它并重现我的问题/找出问题所在。

最佳答案

我将尽力澄清米歇尔·伦格罗讷(MichéeLengronne)的所作所为,我认为他的回答部分正确。
您有两个容器-test(内部运行postgres)和一个未命名的容器,其中包含go应用程序,该容器的名称是在每次容器启动时随机确定的。
这些容器都在同一网络上。那很重要。
当您使用值ports定义8001:5432时,这意味着如果您从定义的网络外部进行连接,并且选择端口8001进行连接,则它将连接到内部的端口5432
但是,如果仅从同一网络内进行连接,则可以省略ports定义,然后继续直接连接到test容器。

(认真选择一个更好的名称,至少为test_database)

这意味着,将容器名称与默认端口(5432)配合使用就足够了。
TL; DR

DATABASE_URL=postgres://short:password@test:5432/shorturl
应该管用

关于postgresql - 尝试在一个连接到另一个容器中的postgres的容器中运行go程序时发生拨号错误(拨号tcp 172.18.0.2:8001:connect:连接被拒绝),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63074145/

相关文章:

python - 使用 SQLAlchemy 定义 PostgreSQL 字符串列的最小长度

python - 设置 psycopg2 时出现问题(PostGreSQL/python 数据库)

docker - 访问在 nvidia-docker 容器中运行的 jupyter notebook 所需的登录密码

Golang 多个 goroutine 通过引用共享同一个变量

go - big.Float 中的 Div 和 Mod

mysql - 具有两个引用的主键

postgresql 安装失败

reactjs - React.js Docker - 找不到模块

docker - IBM Cloud Functions - 使用基于 Docker 的操作存储敏感数据(环境变量)

go - 如何将结构的字段传递给函数?