You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Testcontainers for Go时Ory Hydra容器间连接被拒绝问题排查

容器内连接Ory Hydra出现Connection Refused问题排查

问题现象

在同一Docker网络test-network下,业务容器连接Hydra容器时始终报错:

Post "http://test-hydra:4445/oauth2/introspect": dial tcp 172.19.0.3:4445: connect: connection refused

尝试HTTPS连接同样失败,Hydra容器无日志输出,但外部通过映射端口可正常访问,且docker network inspect确认两容器在同一网络、IP正确。

相关代码

Hydra容器启动代码

func (c ServiceConfig) StartHydraContainer(ctx context.Context) (url string) {

    container, err := tc.GenericContainer(ctx, tc.GenericContainerRequest{
        ContainerRequest: tc.ContainerRequest{
            Image:    "oryd/hydra:v1.10.6",
            Networks: []string{"test-network"},
            NetworkAliases: map[string][]string{
                networkName: {"test-hydra"},
            },
            Env:          c.env(),
            ExposedPorts: []string{"4444/tcp", "4445/tcp"},
            Cmd:          []string{"serve", "all"},
            WaitingFor:   wait.ForLog("Thank you for using ORY Hydra v1.10.6!"),
        },
        Started: true,
    })

    if err != nil {
        log.Fatal("Hydra start error:", err)
    }

    return fmt.Sprintf("https://test-hydra:4445")
}

业务服务容器代码

func (t ServiceConfig) StartContainer(ctx context.Context) string {
    dir, _ := os.Getwd()

    _, err := tc.GenericContainer(ctx, tc.GenericContainerRequest{
        ContainerRequest: tc.ContainerRequest{
            FromDockerfile: tc.FromDockerfile{Context: filepath.Join(dir, "Service")},
            Networks:       []string{"test-network"},
            NetworkAliases: map[string][]string{networkName: {"test-service"}},
            Env:            t.env(),
            ExposedPorts:   []string{"9000/tcp"},
            WaitingFor:     wait.ForExposedPort(),
        },
        Started: true,
    })
    if err != nil {
        log.Fatal(err)
    }

    return fmt.Sprintf("test-service:9000")
}

func (t ServiceConfig) env() map[string]string {
    return map[string]string{"OIDC_PROVIDER_ADDRESS": "https://test-hydra:4445"}
} 

排查方向与解决方案

1. Hydra服务监听地址限制(核心原因)

Ory Hydra默认将服务绑定到127.0.0.1,该地址仅容器自身可见,同一网络的其他容器无法通过容器IP或别名访问。必须指定监听所有接口:

  • 给Hydra添加环境变量HYDRA_ADMIN_LISTEN=0.0.0.0:4445(管理端口)和HYDRA_PUBLIC_LISTEN=0.0.0.0:4444(公共端口)。

修改Hydra容器的env()方法补充变量:

func (c ServiceConfig) env() map[string]string {
    return map[string]string{
        // 保留原有环境变量
        "HYDRA_ADMIN_LISTEN": "0.0.0.0:4445",
        "HYDRA_PUBLIC_LISTEN": "0.0.0.0:4444",
    }
}

2. 启动就绪判断逻辑不准确

当前仅通过日志Thank you for using ORY Hydra v1.10.6!判断启动完成,无法保证服务已完成初始化并监听端口。建议改为同时监听端口就绪:

WaitingFor: wait.ForAll(
    wait.ForLog("Thank you for using ORY Hydra v1.10.6!"),
    wait.ForListeningPort("4445/tcp"),
),

3. 业务容器启动时机问题

业务容器仅等待自身端口开放,可能早于Hydra服务就绪。可在业务服务中添加连接重试逻辑,或者调整启动顺序,确保Hydra完全就绪后再启动业务容器。

4. HTTPS证书校验问题(针对HTTPS连接场景)

如果使用HTTPS连接,业务容器可能不信任Hydra的自签证书(默认生成),可在测试环境临时禁用证书校验:

func (t ServiceConfig) env() map[string]string {
    return map[string]string{
        "OIDC_PROVIDER_ADDRESS": "https://test-hydra:4445",
        "OIDC_SKIP_VERIFY": "true", // 仅测试环境使用
    }
}

总结

最可能的问题是Hydra默认绑定127.0.0.1导致容器间无法访问,添加HYDRA_ADMIN_LISTEN=0.0.0.0:4445即可解决核心问题,同时调整启动等待条件确保服务真正就绪。

内容的提问来源于stack exchange,提问作者Dmitry Malys

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 09:37:45