R Shiny部署至shinyapps.io无法连接GCP托管MySQL数据库
连接失败核心原因
本地能连通是因为你手动启动了Cloud SQL Proxy,把本地127.0.0.1:3307的流量转发到了GCP上的Cloud SQL实例。部署到shinyapps.io或自建Shiny Server后,运行环境里没有这个代理进程,加上GCP Cloud SQL默认会拦截所有未授权的公网访问请求,直接填实例公网IP自然无法连通。
部署后连通Cloud SQL的配置方法
两种方案可选,根据自身场景选择即可:
- 方案1(通用推荐,无需配置公网白名单)
不管是shinyapps.io托管还是自建Shiny Server都能用,逻辑和本地跑代理完全一致:- 下载Linux amd64架构的
cloud_sql_proxy二进制文件,放到Shiny项目根目录,部署时随代码一起上传 - 在GCP控制台创建服务账号,给它绑定
Cloud SQL Client权限,下载对应的JSON密钥文件,也放到项目根目录。注意这个密钥文件绝对不能传到公开代码仓库 - 部署前记得给本地项目里的
cloud_sql_proxy文件开可执行权限,避免传到服务器后无法运行
- 下载Linux amd64架构的
- 方案2(公网直连模式,无需打包二进制)
- 查询shinyapps.io官方公布的全量出口IP段,全部加到Cloud SQL实例的「公网IP-授权网络」列表里;如果是自建Shiny Server,直接添加服务器的固定公网IP即可
- 开启Cloud SQL的强制SSL连接,避免公网传输数据泄露
- 提前从GCP控制台下载SSL连接需要的客户端证书,放到项目目录里
本地/云环境兼容代码写法
通过环境变量判断当前运行环境,自动切换逻辑,不用每次部署都手动改代码:
- 先在本地电脑的
.Renviron文件里加一行APP_ENV=local,标记为本地开发环境;到shinyapps.io/自建Shiny Server的环境变量配置页,添加APP_ENV=cloud的环境变量标记生产环境 - 数据库连接代码直接放在全局初始化位置(
global.R或者app.R最顶部),参考如下:
library(pool) library(RMySQL) # 生产环境自动拉起Cloud SQL Proxy if (Sys.getenv("APP_ENV") == "cloud") { # 走方案1的话,启动proxy进程:替换成你自己的实例连接名、密钥文件名 system2("./cloud_sql_proxy", args = c("-instances=你的GCP项目ID:实例区域:CloudSQL实例名=tcp:3307", "-credential_file=./你的服务账号密钥.json"), wait = FALSE, stdout = NULL, stderr = NULL) # 等待2秒待proxy启动完成再连接数据库 Sys.sleep(2) } # 本地、云环境统一连本地127.0.0.1:3307端口,逻辑完全一致 pool <- dbPool( drv = RMySQL::MySQL(), dbname = 'XXXXXX', username = 'XXXXXX', password = 'XXXXXX', host = '127.0.0.1', port = 3307 ) # 应用退出时自动关闭连接池 onStop(function() { poolClose(pool) })
如果选择公网直连的方案2,就去掉上面启动proxy的分支,在环境判断逻辑里单独给云环境配置host(填实例公网IP)、port(默认3306)、SSL证书路径参数即可。
避坑提醒
- 数据库账号密码、服务账号密钥不要硬写在代码里,全部通过环境变量读取,避免凭证泄露
- 用方案1的话,一定要下载Linux版本的cloud_sql_proxy,别把本地Mac/Windows的二进制传上去,否则肯定启动失败
- 部署后如果还是报启动错误,直接查看应用运行日志,先确认是proxy没跑起来、还是账号密码/IP白名单配置错误,不要盲目修改host参数碰运气
内容的提问来源于stack exchange,提问作者vhio
相关产品推荐
相关产品推荐

