Docker化R Shiny应用时如何保留项目目录结构?
问题:Shiny应用Docker化后脚本路径引用不一致
我构建了一个具有如下目录结构的R Shiny应用:
->Dockerfile ->install_packages.R ->app (Folder) ->app/global.R ->app/ui.R ->app/server.R ->app/R (Folder) ->app/R/Folder A with further subfolders with server/ui scripts ->app/R/Folder B with further subfolders with server/ui scripts
本地运行该应用时,我在global.R中通过如下方式调用子目录中的脚本:
source("R/Folder A/MyScript_UI.R")
但使用如下Dockerfile将应用Docker化后,目录结构似乎“丢失”,需要改为如下方式才能调用文件:
source("Folder A/MyScript_UI.R")
这非常不便,因为开发时要用source("R/...),部署时却要删除"R/"。请问我哪里操作错误?
Dockerfile内容如下:
FROM rocker/shiny:latest RUN apt-get update && apt-get install -y --no-install-recommends \ sudo \ pandoc \ pandoc-citeproc \ libcurl4-gnutls-dev \ libcairo2-dev \ libxt-dev \ libssl-dev \ libssh2-1-dev \ libxml2 \ libglu1-mesa\ && rm -rf /var/lib/apt/lists/* COPY install_packages.R /install_packages.R RUN Rscript /install_packages.R COPY ./app/* /home/app/ EXPOSE 3838 CMD ["R", "-e", "shiny::runApp('/home/app', host = '0.0.0.0', port = 3838)"]
原因与解决方法
错误原因
问题出在Dockerfile的COPY命令:
COPY ./app/* /home/app/
这个命令会把app目录下的所有内容(包括R文件夹)直接平铺到/home/app/根目录,破坏了原本app/R的层级结构——本地的app/R/Folder A在容器里变成了/home/app/Folder A,自然找不到R/开头的路径。
修正方法
方法1:修正COPY命令(最直接)
把COPY命令改成复制整个app目录到目标路径,保留原层级:
COPY ./app /home/app/
复制完成后,容器内的目录结构和本地完全一致:
/home/app/ ->global.R ->ui.R ->server.R ->R (Folder) ->R/Folder A... ->R/Folder B...
此时global.R里的source("R/Folder A/MyScript_UI.R")在本地和Docker环境中都能正常工作,无需修改路径。
方法2:使用通用路径写法(兼容多环境)
如果想从代码层面避免路径问题,可以在global.R中用基于应用根目录的路径:
# 用here包获取应用根目录(需先安装here) source(here::here("R", "Folder A", "MyScript_UI.R")) # 或者不用第三方包的写法 app_root <- dirname(sys.frame(1)$ofile) source(file.path(app_root, "R", "Folder A", "MyScript_UI.R"))
内容的提问来源于stack exchange,提问作者Elena
相关产品推荐
相关产品推荐

