You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Go应用在Docker环境中挂起问题求助

排查Go Pub/Sub应用Docker部署挂起问题

Hey Sebastian,这种本地跑正常、Docker里就挂起的坑我之前踩过好几次,结合你的代码片段和场景,大概率是认证、网络或者上下文处理的问题,咱们一步步来定位:

1. 先把被忽略的错误捞出来!

你的代码里topic.Exists(ctx)的错误直接用_忽略了,这是最大的隐患!在本地环境下,你的Go客户端能拿到默认的Google Cloud凭据(比如通过gcloud CLI或者本地的密钥文件),所以不会出错;但到了Docker容器里,一旦认证失败或者网络不通,客户端会一直重试而不报错,看起来就像“挂起”了。

赶紧修改代码,把错误打出来,同时给上下文加超时避免无限等待:

func getOrCreateTopic() {
    log.Infof("1")
    ctx := context.Background()
    // 给上下文添加30秒超时,防止无限阻塞
    ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
    defer cancel()
    log.Infof("2")
    topicName := viper.GetString("gce.pubsub.topic")
    log.Infof("3")
    topic = client.Topic(topicName)
    log.Infof("4")
    exists, err := topic.Exists(ctx)
    if err != nil {
        log.Fatalf("Failed to check topic existence: %v", err)
    }
    log.Infof("Topic exists: %t", exists)
    // 后续逻辑...
}

加了这些之后,你就能看到容器里到底是认证失败、网络不通还是其他问题,而不是瞎猜。

2. 检查Docker里的Google Cloud认证

本地环境下,你可能用的是个人账号的gcloud凭据,但Docker容器默认不会继承这些:

  • 确保你把服务账号密钥文件挂载到了容器里,并且设置了环境变量GOOGLE_APPLICATION_CREDENTIALS指向密钥路径,比如启动命令:
    docker run -v /path/to/your/key.json:/app/key.json -e GOOGLE_APPLICATION_CREDENTIALS=/app/key.json your-go-app-image
    
  • 或者在Dockerfile里把密钥文件COPY进去(注意不要把密钥提交到代码仓库!),并设置对应环境变量。

3. 排查Docker网络连通性

容器的网络可能和本地不一样,导致无法访问Google Cloud的Pub/Sub服务:

  • 进入容器内部,测试网络连通性:
    docker exec -it your-container-name sh
    # 测试能不能访问Pub/SD的API端点
    curl https://pubsub.googleapis.com/v1/projects/your-project-id/topics/your-topic-name
    
    如果返回“401 Unauthorized”说明网络通但认证有问题;如果连不上,那就是网络被拦截了。
  • 如果你的环境需要代理,记得给容器设置HTTP_PROXYHTTPS_PROXY环境变量,Go的标准库会自动读取这些变量。
  • 可以先试试用--network host模式启动容器,如果能正常运行,说明是Docker bridge网络的配置问题,再针对性调整。

4. 检查基础镜像的CA证书

如果你的Docker镜像用的是alpine这类轻量镜像,可能缺少根CA证书,导致HTTPS请求无法验证Google的证书,从而卡住:

  • 要么换成golang:1.21或者debian:bookworm这类带完整CA证书的基础镜像;
  • 要么在alpine的Dockerfile里添加安装CA证书的步骤:
    FROM alpine:latest
    RUN apk add --no-cache ca-certificates
    # 后续构建步骤...
    

按这几个步骤排查,应该能很快找到问题所在!

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

火山引擎 最新活动