You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 09:41:00