Docker and Shiny

Author

Robert W. Walker

Published

March 3, 2023

obertwwalker.github.io

Last updated: 2023-04-06 03:04:17

Timezone: America/Los_Angeles

When it comes to shiny applications, hosting is a perennial concern. The free alternative shinyapps.io works great but limits the number of user applications that can be deployed. One can operate a server and serve the shiny applications for one’s self. To be honest, this solution is probably superior but is also costly insofar as system administration consumes time. There is an in between that is worth exploring.

We could link to the apps and deploy them in the cloud. The most common methods for accomplishing this particular task involve Docker containers and using Docker to run the shiny applications. I want to explore this alternative in what follows.

Docker

docker is a tool for setting up a working environment that can house a shiny server. Colin Fay has a nice post introducing docker. There is also a very nice article on rocker by Eddelbuettel and Boettiger.

Why not just host your own?

One can. The free shiny server can be installed and configured and the process is fairly straightforward. I am coming to believe that it is simply an easier administration task to let containers handle this.

Building a docker image

There are a few steps to this.

shiny-server.conf

I created a shiny-server.conf file to configure the shiny server inside the container. The contents of the file are below.

# Define the user we should use when spawning R Shiny processes
run_as shiny;
# Define a top-level server which will listen on a port
server {
  # Instruct this server to listen on port 3838.
  listen 3838;
# Define the location available at the base URL
  location / {
# Run this location in 'site_dir' mode, which hosts the entire directory
    # tree at '/srv/shiny-server'
    site_dir /srv/shiny-server;
    
    # Define where we should put the log files for this location
    log_dir /var/log/shiny-server;
    
    # Should we list the contents of a (non-Shiny-App) directory when the user 
    # visits the corresponding URL?
    directory_index on;
  }
}

shiny-server.sh

This file invokes the shiny server.

#!/bin/sh
# Make sure the directory for individual app logs exists
mkdir -p /var/log/shiny-server
chown shiny.shiny /var/log/shiny-server
exec shiny-server >> /var/log/shiny-server.log 2>&1

Dockerfile

The dockerfile needs instructions for building R and being able to execute the necessary components. Here is the Dockerfile.

# get shiny server plus tidyverse packages image
FROM rocker/shiny-verse:latest
# system libraries of general use
RUN apt-get update && apt-get install -y \
    sudo \
    pandoc \
    pandoc-citeproc \
    libcurl4-gnutls-dev \
    libcairo2-dev \
    libxt-dev \
    libssl-dev \
    libssh2-1-dev
# install R packages required 
# (change it depending on the packages you need)
RUN R -e "install.packages(c('shinydashboard','DT','hrbrthemes','lubridate'), 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
# Make the ShinyApp available at port 3838
EXPOSE 3838
# 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"]

app.R

The last thing that I require is a functional app. In this case, my app is three panels applied to archigos and an .rda version of the data exists in the container. Here is the total file.

#
# This is a Shiny web application. You can run the application by clicking
# the 'Run App' button above.
#
# Find out more about building applications with Shiny here:
#
#    http://shiny.rstudio.com/
#

library(shiny)
library(bslib)
library(shinydashboard)
library(tidyverse) 
library(magrittr)
library(utf8)
library(shiny)
library(DT)
library(lubridate)
library(hrbrthemes)
# load the data
load("data/archigos.rda")
# create the set of countries
Country.Select <- Archigos %$% table(idacr) %>% data.frame() %>% mutate(Country = idacr) %>% select(Country)
# plot for durations
Plot.Durations <- function(data, state) {
  data %>% ggplot(., aes(x=tenureY)) + geom_histogram() + theme_ipsum_rc() + labs(x="Durations", title=paste0("Durations: ",state))
}
# plot for chronology
Plot.Chronology <- function(data, state) {
  data %>% arrange(eindate) %>% 
    ggplot(., aes(x=fct_reorder(leader, eindate), color=leader)) + geom_errorbar(aes(ymin=eindate, ymax=eoutdate)) + coord_flip() + labs(x="", title=paste0("Leader Chronology: ",state)) + theme_ipsum_rc() + scale_color_viridis_d(option = "E") + guides(color=FALSE)
}

header <- dashboardHeader(title = "Archigos")
sidebar <-  dashboardSidebar(
  sidebarMenu(selectInput(inputId = "Country", label="Country:", choices = Country.Select$Country, selected="AFG"))
)
body <- dashboardBody(
  tabsetPanel(
    tabItem(tabName = "dashb1",
            title="Chronology",
            # Boxes need to be put in a row (or column)
            fluidRow(box(plotOutput("plotDur"), width=12))
    ),
    tabItem(tabName = "dashb2",
            title="Durations",
            fluidRow(box(plotOutput("plotChr"), width=12))
    )),
  fluidRow(DTOutput("plotDT"))
)
ui <- dashboardPage(skin = "purple", header, sidebar, body)

server <- function(input, output) {
  dataset <- reactive({
    Archigos %>% 
      filter(idacr==input$Country) %>% 
      arrange(desc(eoutdate))
  })
  output$plotDT <- renderDT({  dataset()}, options = list(scrollX = TRUE) 
  )
  output$plotDur <- renderPlot({
    Plot.Chronology(dataset(), input$country)
  })
  output$plotChr <- renderPlot({
    Plot.Durations(dataset(), input$country)
  })
}

# Run the application 
shinyApp(ui = ui, server = server)

Building the docker container

At the terminal, here I need to build the docker image.

sudo docker build image -t pieratio/archigos

Pushing to a docker hub

The first one is to go to docker hub. I have an account that has a single container currently there called archigos.

Google cloud services

Next we wander off to cloud.google.com and enable containers for use in Cloud Run. I then set up the project called archigos attached to port 3838 and set it to run. Now I have a running shiny app in the cloud on google to tie to this post!

The app

Another Example

One that Uses .Rmd FlexDashboard

Deploying this container is tricky because of the overall size of the project. I have to limit the number of instances and kick up the amount of usable RAM to make it work. The margins of this page do not render this super well. It is better seen at the host site for that repository.

References

How’s that done?
knitr::write_bib(names(sessionInfo()$otherPkgs), file="bibliography.bib")

References

Arnold, Jeffrey B. 2021. Ggthemes: Extra Themes, Scales and Geoms for Ggplot2. https://github.com/jrnold/ggthemes.
Bache, Stefan Milton, and Hadley Wickham. 2022. Magrittr: A Forward-Pipe Operator for r. https://CRAN.R-project.org/package=magrittr.
Cheng, Joe. 2023. D3scatter: Demo of D3 Scatter Plot; Testbed for Crosstalk Library.
Cheng, Joe, and Carson Sievert. 2021. Crosstalk: Inter-Widget Interactivity for HTML Widgets. https://rstudio.github.io/crosstalk/.
Cheng, Joe, Carson Sievert, Barret Schloerke, Winston Chang, Yihui Xie, and Jeff Allen. 2022. Htmltools: Tools for HTML. https://CRAN.R-project.org/package=htmltools.
Dancho, Matt, and Davis Vaughan. 2022. Tidyquant: Tidy Quantitative Financial Analysis. https://github.com/business-science/tidyquant.
Gohel, David, and Panagiotis Skintzos. 2023. Ggiraph: Make Ggplot2 Graphics Interactive. https://davidgohel.github.io/ggiraph/.
Grolemund, Garrett, and Hadley Wickham. 2011. “Dates and Times Made Easy with lubridate.” Journal of Statistical Software 40 (3): 1–25. https://www.jstatsoft.org/v40/i03/.
Müller, Kirill, and Hadley Wickham. 2022. Tibble: Simple Data Frames. https://CRAN.R-project.org/package=tibble.
Pedersen, Thomas Lin. 2022. Patchwork: The Composer of Plots. https://CRAN.R-project.org/package=patchwork.
Peterson, Brian G., and Peter Carl. 2020. PerformanceAnalytics: Econometric Tools for Performance and Risk Analysis. https://github.com/braverock/PerformanceAnalytics.
Ryan, Jeffrey A., and Joshua M. Ulrich. 2022a. Quantmod: Quantitative Financial Modelling Framework. https://CRAN.R-project.org/package=quantmod.
———. 2022b. Xts: eXtensible Time Series. https://github.com/joshuaulrich/xts.
Sievert, Carson. 2020. Interactive Web-Based Data Visualization with r, Plotly, and Shiny. Chapman; Hall/CRC. https://plotly-r.com.
Sievert, Carson, Chris Parmer, Toby Hocking, Scott Chamberlain, Karthik Ram, Marianne Corvellec, and Pedro Despouy. 2022. Plotly: Create Interactive Web Graphics via Plotly.js. https://CRAN.R-project.org/package=plotly.
Slowikowski, Kamil. 2023. Ggrepel: Automatically Position Non-Overlapping Text Labels with Ggplot2. https://github.com/slowkow/ggrepel.
Spinu, Vitalie, Garrett Grolemund, and Hadley Wickham. 2023. Lubridate: Make Dealing with Dates a Little Easier. https://CRAN.R-project.org/package=lubridate.
Ulrich, Joshua. 2021. TTR: Technical Trading Rules. https://github.com/joshuaulrich/TTR.
Wickham, Hadley. 2016. Ggplot2: Elegant Graphics for Data Analysis. Springer-Verlag New York. https://ggplot2.tidyverse.org.
———. 2022a. Stringr: Simple, Consistent Wrappers for Common String Operations. https://CRAN.R-project.org/package=stringr.
———. 2022b. Tidyverse: Easily Install and Load the Tidyverse. https://CRAN.R-project.org/package=tidyverse.
———. 2023. Forcats: Tools for Working with Categorical Variables (Factors). https://CRAN.R-project.org/package=forcats.
Wickham, Hadley, Mara Averick, Jennifer Bryan, Winston Chang, Lucy D’Agostino McGowan, Romain François, Garrett Grolemund, et al. 2019. “Welcome to the tidyverse.” Journal of Open Source Software 4 (43): 1686. https://doi.org/10.21105/joss.01686.
Wickham, Hadley, Winston Chang, Lionel Henry, Thomas Lin Pedersen, Kohske Takahashi, Claus Wilke, Kara Woo, Hiroaki Yutani, and Dewey Dunnington. 2023. Ggplot2: Create Elegant Data Visualisations Using the Grammar of Graphics. https://CRAN.R-project.org/package=ggplot2.
Wickham, Hadley, Romain François, Lionel Henry, Kirill Müller, and Davis Vaughan. 2023. Dplyr: A Grammar of Data Manipulation. https://CRAN.R-project.org/package=dplyr.
Wickham, Hadley, and Lionel Henry. 2023. Purrr: Functional Programming Tools. https://CRAN.R-project.org/package=purrr.
Wickham, Hadley, Jim Hester, and Jennifer Bryan. 2023. Readr: Read Rectangular Text Data. https://CRAN.R-project.org/package=readr.
Wickham, Hadley, Davis Vaughan, and Maximilian Girlich. 2023. Tidyr: Tidy Messy Data. https://CRAN.R-project.org/package=tidyr.
Xie, Yihui, Joe Cheng, and Xianying Tan. 2023. DT: A Wrapper of the JavaScript Library DataTables. https://github.com/rstudio/DT.
Zeileis, Achim, and Gabor Grothendieck. 2005. “Zoo: S3 Infrastructure for Regular and Irregular Time Series.” Journal of Statistical Software 14 (6): 1–27. https://doi.org/10.18637/jss.v014.i06.
Zeileis, Achim, Gabor Grothendieck, and Jeffrey A. Ryan. 2022. Zoo: S3 Infrastructure for Regular and Irregular Time Series (z’s Ordered Observations). https://zoo.R-Forge.R-project.org/.