Cloud Run中执行Go Migrate连接Cloud SQL遭拒绝问题排查
问题分析与解决方案
一、数据库URI格式错误
你用的postgres://{user}:{password}@cloudsql/{host}:{port}/{db_name}格式完全不对,Cloud Run连接Cloud SQL(PostgreSQL)的正确URI分两种场景:
- Unix套接字连接(推荐,无需额外端口)
正确格式是:
postgres://{user}:{password}@/{db_name}?host=/cloudsql/{connection_name}
这里的{connection_name}就是你的project-name:region-name:instance-name,这种方式通过Cloud Run挂载的Unix套接字直接对接Cloud SQL,不需要指定端口。
- TCP连接(需搭配Cloud SQL Auth Proxy)
如果要走TCP,得先在容器内启动Cloud SQL Auth Proxy,此时URI要指向代理的本地端口(默认5432):
postgres://{user}:{password}@127.0.0.1:5432/{db_name}
但这种方式需要在Dockerfile里添加代理的下载、启动命令,不如Unix套接字简洁。
二、Cloud Run配置遗漏项
你大概率没做这两个关键配置:
- 部署时必须关联Cloud SQL实例:用CLI部署要加
--add-cloudsql-instances={connection_name}参数;在Cloud Console里配置Cloud Run服务时,找到「Cloud SQL连接」选项添加你的实例。 - 给Cloud Run服务账号加权限:确保服务账号拥有
Cloud SQL Client角色,否则连不上Cloud SQL。
三、Go项目数据库迁移的更优方案
1. 部署流程中独立执行迁移(推荐)
别把迁移和应用启动绑在一起,直接在GitHub Action部署流程里单独跑迁移:
- 在Action中用Cloud SQL Auth Proxy连接Cloud SQL,再执行golang migrate命令。
- 这样能在部署前验证迁移是否成功,不会因为迁移失败导致应用启动炸锅。
- 核心Action步骤示例:
- name: Run DB migrations env: DB_URI: postgres://${{ secrets.DB_USER }}:${{ secrets.DB_PASSWORD }}@127.0.0.1:5432/${{ secrets.DB_NAME }} run: | # 下载Cloud SQL Auth Proxy wget https://dl.google.com/cloudsql/cloud_sql_proxy.linux.amd64 -O cloud_sql_proxy chmod +x cloud_sql_proxy # 启动代理后台运行 ./cloud_sql_proxy -instances=${{ secrets.CLOUD_SQL_CONNECTION_NAME }}=tcp:5432 & # 等待代理初始化 sleep 5 # 执行迁移 migrate -database "$DB_URI" -path ./migrations up
2. 应用内迁移的改进(如果坚持要在启动时跑)
- 加连接重试逻辑:数据库连接可能因网络延迟失败,不要一次性报错退出,循环重试几次。
- 用正确的DSN格式,比如Unix套接字的写法:
import ( "database/sql" "fmt" "os" _ "github.com/lib/pq" ) func getDB() (*sql.DB, error) { dsn := fmt.Sprintf("postgres://%s:%s@/%s?host=/cloudsql/%s", os.Getenv("DB_USER"), os.Getenv("DB_PASSWORD"), os.Getenv("DB_NAME"), os.Getenv("CLOUD_SQL_CONNECTION_NAME"), ) return sql.Open("postgres", dsn) }
四、代码片段补充提醒
虽然没看到你的代码截图,但要注意:
- 所有数据库凭证、连接名都通过Cloud Run环境变量传递,别硬编码。
- 连接数据库时加上上下文超时,避免无限等待。
内容的提问来源于stack exchange,提问作者Fidriyanto Rizkillah
相关产品推荐
相关产品推荐

