Linux系统下Docker容器内Shiny应用连接外部MySQL数据库配置咨询
问题核心原因
你的app.R中数据库连接的host配置为localhost,受Docker网络隔离特性限制,容器内的localhost指向容器本身而非外部运行的MySQL服务,因此无法建立连接。
1 调整app.R配置
建议通过环境变量传入数据库配置,避免硬编码敏感信息,同时方便部署时灵活修改:
## libraries library(tidyverse) library(shiny) library(shinydashboard) library(ggplot2) library(DBI) library(RMySQL) # shiny dashboard UI ui <- dashboardPage( dashboardHeader(), dashboardSidebar(), dashboardBody( fluidPage( plotOutput("plot1") ) ) ) # shiny dashboard server server <- function(input, output,session) { # 从环境变量读取数据库配置,默认值可保留本地调试用 db_host <- Sys.getenv("DB_HOST", "localhost") db_user <- Sys.getenv("DB_USER", "root") db_pwd <- Sys.getenv("DB_PWD", "#####") db_name <- Sys.getenv("DB_NAME", "Archenar") db_port <- as.integer(Sys.getenv("DB_PORT", 3306)) #connection to database orders <- dbConnect(RMySQL::MySQL(), user = db_user, password = db_pwd, dbname = db_name, host = db_host, port = db_port) # 新增:会话结束自动断开连接,避免连接泄漏 session$onSessionEnded(function() { dbDisconnect(orders) }) # 优化:checkFunc无需每次查询全表,用count减少资源消耗 rigel <- reactivePoll(5000, session,checkFunc = function() { query2= "SELECT count(*) FROM SENSOR" rs = dbSendQuery(orders,query2) dbFetch(rs) }, valueFunc = function() { query2= "SELECT * FROM SENSOR" rs = dbSendQuery(orders,query2) dbFetch(rs) } ) #make plot output$plot1 <- renderPlot({ rigelp <- rigel() %>% as.data.frame()%>% group_by(category) %>% summarize(v=sum(value1)) ggplot(rigelp,aes(x=category,y=v)) + geom_bar(stat = "identity") }) } shinyApp(ui, server)
2 调整Docker相关配置
2.1 优化Dockerfile(可选)
你当前的Dockerfile依赖已满足需求,可将分散的R包安装命令合并,减少镜像层数:
# get shiny server plus tidyverse packages image FROM rocker/shiny:latest # system libraries of general use RUN apt-get update && apt-get install -y \ sudo \ pandoc \ pandoc-citeproc \ libcurl4-gnutls-dev \ libcairo2-dev \ libmariadbd-dev \ libxt-dev \ libssl-dev \ libssh2-1-dev # 合并R包安装命令 RUN R -e "install.packages(c('shiny','tidyverse','shinydashboard','DBI','RMySQL'),repos='http://cran.rstudio.com/')" # Copy configuration files into the Docker image COPY shiny-server.conf /etc/shiny-server/shiny-server.conf COPY /app /srv/shiny-server/ RUN rm /srv/shiny-server/index.html # 注意:与shiny-server.conf中监听端口保持一致,当前配置监听80,这里对应EXPOSE 80 EXPOSE 80 # Copy further configuration files into the Docker image COPY shiny-server.sh /usr/bin/shiny-server.sh RUN ["chmod", "+x", "/usr/bin/shiny-server.sh"] CMD ["/usr/bin/shiny-server.sh"]
2.2 启动容器时传入数据库配置
启动容器时通过环境变量传入实际的MySQL连接信息,根据你的MySQL部署位置选择对应配置:
- 如果MySQL部署在运行Docker的Ubuntu宿主机上:建议将
DB_HOST设为宿主机的局域网IP,或添加--net=host参数直接使用宿主机网络 - 如果MySQL是云数据库服务:直接将
DB_HOST设为数据库的公网/内网连接地址,同时提前将云服务器IP加入数据库访问白名单
示例启动命令:
docker run -d -p 宿主机端口:80 \ -e DB_HOST=你的MySQL服务实际IP地址 \ -e DB_USER=数据库用户名 \ -e DB_PWD=数据库密码 \ -e DB_NAME=Archenar \ 你构建的Shiny镜像名称
3 常见问题排查
- 先确认MySQL服务正常运行,3306端口未被防火墙拦截
- 确认数据库用户允许你配置的IP访问,不要仅限制localhost登录
- 可进入容器内部测试网络连通性:执行
docker exec -it 容器ID bash进入容器,安装mysql-client后手动尝试连接数据库,先排除网络问题再排查代码问题
内容的提问来源于stack exchange,提问作者Jonathan Livingston Seagull
相关产品推荐
相关产品推荐

