Docker部署的Shiny应用无法读取每日更新数据的问题求助
问题描述
我开发了一个Docker化的Shiny应用,从服务器上的/myapp1/app/data文件夹读取数据,该文件夹内的数据每日都会更新。当应用在域名上运行时,能读取到文件夹中的初始数据,但数据更新后,应用无法读取新数据,仍仅读取旧数据;只有停止并重新启动容器后,应用才能读取到新数据。
我的Dockerfile内容
# get shiny server and R from the rocker project FROM rocker/shiny:4.0.5 RUN apt-get update && apt-get install -y \ sudo \ gdebi-core \ pandoc \ pandoc-citeproc \ libcurl4-gnutls-dev \ libxt-dev \ libssl-dev \ libxml2 \ libxml2-dev \ libsodium-dev # install R packages required RUN R -e "install.packages(c('shiny', 'shinythemes', 'dygraphs', 'shinyWidgets', 'manipulateWidget', 'DT', 'zoo', 'shinyjs','emayili', 'wordcloud2', 'rmarkdown', 'xts', 'shinyauthr', 'curl', 'jsonlite', 'httr', 'lubridate'), repos='http://cran.rstudio.com/')" # copy the app directory into the image WORKDIR /myapp1/app COPY app . # run app EXPOSE 8090 CMD ["R", "-e", "shiny::runApp('/myapp1/app', host = '0.0.0.0', port = 8090)"]
我的docker-compose.yml内容
version: "3.7" services: app1: image: myapp1image container_name: myapp1container expose: - "8090" environment: - VIRTUAL_PORT=8090 - VIRTUAL_HOST=myapp1.net,www.myapp1.net - LETSENCRYPT_HOST=myapp1.net,www.myapp1.net - LETSENCRYPT_EMAIL=info@myapp1.net volumes: - /myapp1/app/data:/myapp1/app/data networks: - mynetwork networks: mynetwork: external : true
解决方案
问题核心是Shiny应用启动时一次性加载了数据,之后没有主动重新读取更新后的文件。以下是两种可行的解决方法:
方法1:添加自动定时刷新逻辑
在Shiny的server函数中,使用reactivePoll定期检查数据文件的修改时间,自动触发数据重新读取:
server <- function(input, output, session) { # 定义数据读取函数,替换为你实际的读取逻辑 load_latest_data <- function() { read.csv("/myapp1/app/data/your_data_file.csv") } # 每1小时检查一次文件修改时间,自动刷新数据(可调整间隔,单位:毫秒) latest_data <- reactivePoll( intervalMillis = 3600000, session = session, checkFunc = function() { # 获取文件最后修改时间,作为是否刷新的判断依据 file.info("/myapp1/app/data/your_data_file.csv")$mtime }, valueFunc = load_latest_data ) # 后续所有依赖数据的输出都使用latest_data()获取最新内容 output$data_table <- renderDT({ datatable(latest_data()) }) }
方法2:添加手动刷新按钮
如果不需要自动刷新,可给用户提供手动触发数据更新的按钮:
ui <- fluidPage( actionButton("refresh_btn", "刷新最新数据"), DTOutput("data_table") ) server <- function(input, output, session) { # 用reactiveVal存储数据 current_data <- reactiveVal() # 初始加载数据 observe({ current_data(read.csv("/myapp1/app/data/your_data_file.csv")) }) # 点击按钮时重新读取数据 observeEvent(input$refresh_btn, { current_data(read.csv("/myapp1/app/data/your_data_file.csv")) }) output$data_table <- renderDT({ datatable(current_data()) }) }
额外注意事项
- 确保容器内的Shiny进程(默认用户为
shiny)有权限读取挂载的/myapp1/app/data目录,可在服务器执行chown -R shiny:shiny /myapp1/app/data调整权限。 - 若数据文件体积较大,需合理设置自动刷新间隔,避免频繁读取影响应用性能。
内容的提问来源于stack exchange,提问作者Citizen
相关产品推荐
相关产品推荐

