Golang Testcontainers网络问题:微服务无法连接PostgreSQL容器
微服务测试容器无法连接PostgreSQL测试容器问题
我正在为Golang微服务(基于Fiber和Gorm框架)编写测试,需要创建Docker网络,将PostgreSQL测试容器和微服务测试容器接入同一网络,但微服务始终无法连接到数据库。
DB连接配置(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 }
Testcontainers配置
PostgreSQL容器配置
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, })
尝试过的方法及错误
我尝试了多种HOST和DB_PORT组合,均失败:
通过容器名称获取HOST:
prescriptionDBHost, err := prescriptionDBContainer.Name(context.Background()) // 配置:"HOST": prescriptionDBHost, "DB_PORT": prescriptionDBPort.Port()错误:
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去除容器名称中的"/":
"HOST": strings.Trim(prescriptionDBHost,"/"), "DB_PORT": prescriptionDBPort.Port()出现类似dial tcp错误。
使用localhost/127.0.0.1作为HOST:
"HOST": "localhost", "DB_PORT": prescriptionDBPort.Port() // 或 "HOST": "127.0.0.1", "DB_PORT": prescriptionDBPort.Port()错误:
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)通过容器IP获取HOST:
prescriptionDBHost, err := prescriptionDBContainer.ContainerIP(context.Background()) // 配置:"HOST": prescriptionDBHost, "DB_PORT": prescriptionDBPort.Port()同样出现dial tcp错误。
额外调试:暂停测试后,手动用localhost+对应端口连接数据库容器可以成功,但docker network inspect显示数据库容器已接入网络,微服务容器未接入。
解决方法
1. 修正网络别名冲突
给两个容器设置了同一个网络别名db-network会导致DNS解析混乱,给PostgreSQL容器单独设置唯一别名,比如postgres-db:
// PostgreSQL容器的NetworkAliases配置 NetworkAliases: map[string][]string{ network.Name: {"postgres-db"}, },
微服务容器的网络别名可换成其他名称,比如prescription-service,避免冲突。
2. 使用容器网络别名+内部端口通信
在同一Docker网络内,容器之间直接用网络别名+容器内部端口通信,不需要主机映射的随机端口。修改微服务容器的环境变量:
Env: map[string]string{ // ...其他配置 "HOST": "postgres-db", "DB_PORT": "5432", },
3. 确保网络与容器初始化顺序
确认Docker网络已提前创建完成:
network, err := testcontainers.GenericNetwork(context.Background(), testcontainers.GenericNetworkRequest{ NetworkRequest: testcontainers.NetworkRequest{ Name: "test-network", // 自定义网络名称 }, }) if err != nil { panic(err) }
同时,微服务容器的WaitingFor仅监听8080端口可能不够,可添加等待数据库连接成功的逻辑,或延长等待时间确保网络完全就绪。
4. 验证容器网络状态
创建容器后打印网络信息,确认两个容器都在同一网络:
// 打印PostgreSQL容器网络信息 dbNetworks, err := prescriptionDBContainer.Networks(context.Background()) if err != nil { panic(err) } fmt.Println("DB容器网络:", dbNetworks) // 打印微服务容器网络信息 serviceNetworks, err := prescriptionContainer.Networks(context.Background()) if err != nil { panic(err) } fmt.Println("微服务容器网络:", serviceNetworks)
完成以上步骤后,微服务容器应该能通过postgres-db别名和5432端口正常连接到PostgreSQL容器。
内容的提问来源于stack exchange,提问作者PLSHELP
相关产品推荐
相关产品推荐

