我正在try 在我的微服务中创建一些测试,我想创建一个网络,将我的数据库测试容器(Postgres)和我的微服务测试容器附加到该网络上.无论我怎么try ,我都无法让我的微服务连接到数据库.我的微服务是使用光纤和GORM的Golang.我try 在如下所示的db.go配置文件中连接到数据库:

func SetupDB(port string, host string) *gorm.DB {

    dsn := "host=" + host + " user=postgres password=password dbname=prescription port=" + port + " sslmode=disable"

    db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})

    if err != nil {
        panic("error connecting to database")
    }

    db.AutoMigrate(&model.Prescription{})

    return db
}

下面是我的测试容器的外观:

    prescriptionDBContainer, err := testcontainers.GenericContainer(context.Background(), testcontainers.GenericContainerRequest{
        ContainerRequest: testcontainers.ContainerRequest{
            Image:        "postgres",
            ExposedPorts: []string{postgresPort.Port()},
            Env: map[string]string{
                "POSTGRES_USER":     "postgres",
                "POSTGRES_PASSWORD": "password",
                "POSTGRES_DB":       "prescription",
            },
            Networks: []string{network.Name},
            NetworkAliases: map[string][]string{
                network.Name: {"db-network"},
            },
            WaitingFor: wait.ForAll(
                wait.ForLog("database system is ready to accept connections"),
                wait.ForListeningPort(postgresPort),
            ),
        },
        Started: true,
    })
prescriptionContainer, err := testcontainers.GenericContainer(context.Background(), testcontainers.GenericContainerRequest{
        ContainerRequest: testcontainers.ContainerRequest{
            FromDockerfile: testcontainers.FromDockerfile{Context: "../../../../prescription"},
            Networks:       []string{network.Name},
            NetworkAliases: map[string][]string{
                network.Name: {"db-network"},
            },
            Env: map[string]string{
                "POSTGRES_USER":     "postgres",
                "POSTGRES_PASSWORD": "password",
                "POSTGRES_DB":       "prescription",
                "HOST":              prescriptionDBHost,
                "DB_PORT":           prescriptionDBPort.Port(),
            },
            ExposedPorts: []string{pMicroPort.Port()},
            WaitingFor:   wait.ForListeningPort("8080"),
        },
        Started: true,
    })

也许这是因为我不能从根本上理解在docker中联网时发生的一些事情,但我真的很困惑,当我为host和DB_Port设置环境时(我已经try 了所有的组合),它拒绝将微服务连接到数据库

在我的微服务的测试容器中,我try 了:

"HOST":              prescriptionDBHost,
"DB_PORT":           prescriptionDBPort.Port(),

RepuptionDBhost通过以下方式提取:

prescriptionDBHost, err := prescriptionDBContainer.Name(context.Background())

这会导致错误消息:

failed to initialize database, got error failed to connect to `host=/stoic_heyrovsky user=postgres database=prescription`: dial error (dial unix /stoic_heyrovsky/.s.PGSQL.53802: connect: no such file or directory)
panic: error connecting to database

然后,我try 从主机名中删除"/",如下所示:

"HOST":              strings.Trim(prescriptionDBHost,"/"),
"DB_PORT":           prescriptionDBPort.Port(),

我也试过了:

"HOST":              "localhost",
"DB_PORT":           prescriptionDBPort.Port(),
"HOST":              "127.0.0.1",
"DB_PORT":           prescriptionDBPort.Port(),
prescriptionDBHost, err := prescriptionDBContainer.ContainerIP(context.Background())

"HOST":              prescriptionDBHost,
"DB_PORT":           prescriptionDBPort.Port(),

这里的最后4个示例都导致了某种类型的拨号TCP错误,例如:

failed to initialize database, got error failed to connect to `host=localhost user=postgres database=prescription`: dial error (dial tcp [::1]:53921: connect: cannot assign requested address)

在测试容器创建数据库容器之后,我还进行了调试并停止,然后转到我的微服务,并使用DB_HOST=LOCALHOST和PORT=硬编码连接到该容器,这是成功的,所以我真的不知道出了什么问题.我能想到的唯一一件事是微服务容器在try 连接到数据库之前没有连接到网络.我做了一个对接网络判断,我可以看到数据库容器已附加,但微服务从未附加(但可能只是因为其他原因?).

推荐答案

您可以这样做:

prescriptionDBContainer, err := testcontainers.GenericContainer(context.Background(), testcontainers.GenericContainerRequest{
    ContainerRequest: testcontainers.ContainerRequest{
        Image:        "postgres",
        ExposedPorts: []string{"5432/tcp"},
        Env: map[string]string{
            "POSTGRES_USER":     "postgres",
            "POSTGRES_PASSWORD": "password",
            "POSTGRES_DB":       "prescription",
        },
        Networks:       []string{networkName},
        NetworkAliases: map[string][]string{networkName: []string{"postgres"}},
        WaitingFor: wait.ForAll(
            wait.ForLog("database system is ready to accept connections"),
            wait.ForListeningPort("5432/tcp"),
        ),
    },
    Started: true,
})
if err != nil {
    t.Fatal(err)
}

prescriptionContainer, err := testcontainers.GenericContainer(context.Background(), testcontainers.GenericContainerRequest{
    ContainerRequest: testcontainers.ContainerRequest{
        FromDockerfile: testcontainers.FromDockerfile{Context: "./testapp"},
        ExposedPorts:   []string{"8080/tcp"},
        Networks:       []string{networkName},
        NetworkAliases: map[string][]string{networkName: []string{"blah"}},
        Env: map[string]string{
            "DATABASE_URL": "postgres://postgres:password@postgres:5432/prescription",
        },
        WaitingFor: wait.ForListeningPort("8080/tcp"),
    },
    Started: true,
})

注意NetworkAliases的配置方式;在您的代码中,您将两者都设置为db-network,但我猜这是由于误解.该设置配置了一个可以引用容器的别名(在本例中,我为postgres容器使用postgres;这意味着当连接HOST时,根据上面示例中使用的URL,将是postgres).

作为替代方案,您可以使用port, err := prescriptionDBContainer.MappedPort(context.Background(), "5432/tcp")将端口expose 在主机上,然后连接到端口port.Port()上的host.docker.internal.当正在测试的应用程序在主机上运行而不是在容器中运行时,经常使用此方法(但在这种情况下,您将连接到localhost并使用从MappedPort()返回的报告).

Go相关问答推荐

向API网关终结点发出POST请求时出现AWS Lambda With Go:";Rune me.InvalidEntrypoint";错误

Golang应用程序:所请求的资源上不存在HTTP-Control-Allow-Origin标头

你能把用户界面文件中的GTK4应用程序窗口添加到GTK4应用程序中吗?

golang 的持久隐蔽服务

如何在S汇编器中更高效地将全局数据加载到霓虹灯寄存器?

Go:如何在不加载正文的情况下创建 http 代理通行证

3 字节切片和有符号整数类型之间的转换

以编程方式取消 pyspark dataproc 批处理作业(job)

xml.Unmarshal 不支持的类型 struct

如何在 Golang 中打印 2 列表?

使用 Go 根据 /etc/shadow 文件中的散列密码验证密码

如何从 Asterisk Manager Interface Event 获取活动呼叫数

Go 中如何调用测试函数?

如何在 gocql 中设置最大池大小?

Go Colly 如何找到请求的元素?

如何将元素从一个切片移动到另一个切片

如何在切片增长时自动将切片的新元素添加到函数参数

Wire google Inject with multi return from provider 函数

如何使用 Docker 引擎 SDK 和 Golang 运行 docker 挂载卷

try 运行 docker-compose up -d 时出现错误