Golem框架Shiny应用在Google Cloud Run部署时图片路径配置问题
问题描述
目标
在Shiny应用中渲染多个以图片为分面标签的ggplot图表,完整源码可查看对应GitHub仓库。
细节与问题
需创建两个共用同一批图片的图表。在常规Shiny应用中,可在global.R中读取图片后在服务器端生成图表。在Golem框架下,创建了R/global.R文件,代码如下:
labels_flowers <- c( setosa = paste0("<img src='", "inst/app/www", "/", "setosa.jpg' width='100'/>"), versicolor = paste0("<img src='", "inst/app/www", "/", "versicolor.jpg' width='100'/>"), virginica = paste0("<img src='", "inst/app/www", "/", "virginica.jpg' width='100'/>") )
随后在两个模块中使用该变量。
模块示例
模块代码如下:
#' plot UI Function #' #' @description A shiny Module. #' #' @param id,input,output,session Internal parameters for {shiny}. #' #' @noRd #' #' @import shiny #' @import ggplot2 #' @import ggtext mod_plot_ui <- function(id){ ns <- NS(id) tagList( plotOutput(ns("myplot")) ) } #' plot Server Functions #' #' @noRd mod_plot_server <- function(id, data){ moduleServer( id, function(input, output, session){ ns <- session$ns output$myplot <- renderPlot({ ggplot(data = data()) + geom_histogram(aes(Sepal.Length)) + facet_wrap(~ Species, labeller = as_labeller(labels_flowers)) + theme(strip.text.x = ggtext::element_markdown(size = 20)) }) }) }
app_ui.R和app_server.R中对模块的调用方式如下:
app_ui.R
#' The application User-Interface #' #' @param request Internal parameter for `{shiny}`. #' DO NOT REMOVE. #' @import shiny #' @noRd app_ui <- function(request) { tagList( # Leave this function for adding external resources golem_add_external_resources(), # Your application UI logic fluidPage( h1("example"), mod_plot_ui("plot1"), mod_plot2_ui("plot2") ) ) } #' Add external Resources to the Application #' #' This function is internally used to add external #' resources inside the Shiny application. #' #' @import shiny #' @importFrom golem add_resource_path activate_js favicon bundle_resources #' @noRd golem_add_external_resources <- function() { add_resource_path( "www", app_sys("app/www") ) tags$head( favicon(), bundle_resources( path = app_sys("app/www"), app_title = "example" ) # Add here other external resources # for example, you can add shinyalert::useShinyalert() ) }
app_server.R
#' The application server-side #' #' @param input,output,session Internal parameters for {shiny}. #' DO NOT REMOVE. #' @import shiny #' @import ggplot2 #' @import ggtext #' @noRd app_server <- function(input, output, session) { df_iris <- reactive(iris) mod_plot_server("plot1", df_iris) mod_plot2_server("plot2", df_iris) }
部署问题
应用在本地和shinyapps上运行正常,但通过Docker部署到Google Cloud Run时出现错误:
解决方案
问题核心是图片路径配置不符合Golem部署后的资源映射规则,以及Docker环境下的文件结构差异。需做以下修改:
1. 修正R/global.R中的图片路径
Golem框架会将inst/app/www目录构建后映射到/www路径下,直接使用映射后的路径即可,无需硬编码开发时的目录结构:
labels_flowers <- c( setosa = paste0("<img src='/www/setosa.jpg' width='100'/>"), versicolor = paste0("<img src='/www/versicolor.jpg' width='100'/>"), virginica = paste0("<img src='/www/virginica.jpg' width='100'/>") )
2. 确保Dockerfile正确处理资源文件
如果使用rocker/shiny类镜像,需保证Golem构建后的app/www目录被正确复制到容器中,典型Dockerfile示例:
# 基础镜像 FROM rocker/shiny:latest # 安装依赖 RUN apt-get update && apt-get install -y \ libssl-dev \ libcurl4-openssl-dev \ libfontconfig1-dev \ libharfbuzz-dev \ libfribidi-dev \ libpng-dev \ libtiff5-dev \ libjpeg-dev # 安装R包 RUN R -e "install.packages(c('shiny', 'ggplot2', 'ggtext', 'golem'))" # 复制应用文件 COPY . /app WORKDIR /app # 启动应用 CMD ["R", "-e", "shiny::runApp(appDir = '/app', host = '0.0.0.0', port = as.numeric(Sys.getenv('PORT')))"]
3. 验证资源路径有效性
可在app_ui.R中添加测试代码,确认图片路径是否正确:
tags$img(src = "/www/setosa.jpg", width = "100px")
若该图片能正常显示,说明路径配置无误,ggplot分面标签的图片也能正常加载。
内容的提问来源于stack exchange,提问作者umair durrani
相关产品推荐
相关产品推荐

