Introduction
This is the second post in a series about turning data science products written in R into products that can be consumed by technical and non-technical colleagues who don’t use R, without any significant additional infrastructure. As I discussed in more detail in the first post, this requires taking advantage of common DevOps workflows and approaches involving Docker.
Why Shiny?
Most R users will have heard of Shiny, it is an R package that makes it exceptionally easy to turn some R code into an interactive web application. If you haven’t heard of it then take a look at the Shiny Gallery for some examples.
How are Shiny apps typically deployed and used?
Shiny apps are initially developed and used interactively within an RStudio session, and the code can be shared between R users relatively easily. If there is a requirement for a non-R user to use a Shiny application, then RStudio’s Shiny Server can host apps on a central server and has an open source and Pro version available. A Software-as-a-service option version of Shiny Server is also available called ShinyApps.io, whilst RStudio Connect offers even more functionality including hosting Shiny apps.
Why Dockerize then?
Given all of these options for hosting Shiny apps, what role does Docker play? As I explained in my first post, assuming that you don’t want to host your Shiny app in the public domain then you either have to rely on your collaborator to be able to know enough about R to run your app in RStudio, or to have some secure hosting infrastructure available. Dockerizing a Shiny app gives the option that your collaborator only needs to know the basics of git, the command line, and Docker, and nothing about R or Shiny.
An example
As in the first post, we are using the famous gapminder dataset. The scenario is that we have written a very simple shiny app to interactively explore the data via some basic plots, and we want to share that app with someone who isn’t familiar with R but has got at least a basic understanding of Docker and Git.
The git repo
Running instructions
The code for these blog posts is on GitHub - https://github.com/chapmandu2/gapminder-pipeline/. In this post we are considering the code in the directory 02-shiny-app
. Within this repo there are three files in the top directory and a further file in the plot-app
subdirectory:
- plot-app
- app.R
- Dockerfile
- Makefile
- shiny-server.conf
These four files contain all of the information needed to run the Shiny app.
To run the app:
- type
git clone https://github.com/chapmandu2/gapminder-pipeline
(if you haven’t already) - navigate to the
02-shiny-app
directory - type
make run
- two windows will open in firefox (if available)
- one browser window will open RStudio Server at
http://localhost:8787
- the second browser window will open Shiny Server at
http://localhost:3838/users/rstudio
- click on
plot-app
in the second window to open the shiny app.
The Dockerfile
The Dockerfile builds on that used in the first post by installing and configuring Shiny Server:
FROM rocker/verse:3.5.2
# add shiny server
RUN export ADD=shiny && bash /etc/cont-init.d/add
################
#install linux deps
################
RUN apt-get update -y && \
apt-get install -y \
curl
################
#install R packages
################
RUN R -e "install.packages(c('gapminder'))"
################
# configure shiny server
################
COPY ./shiny-server.conf /etc/shiny-server/shiny-server.conf
COPY ./plot-app /home/rstudio/ShinyApps/plot-app/
RUN chown -hR rstudio:rstudio /home/rstudio/ShinyApps
The base image is rocker/verse
from the Rocker project, but this Dockerfile takes advantage of the functionality provided with the Rocker images to add Shiny Server as well as RStudio Server. It then runs the commands to install linux utilities and the gapminder R package. Finally it configures Shiny Server by copying a shiny-server configuration file shiny-server.conf
into the image, as well as the contents of the plot-app
directory. Finally it sets the appropriate owner permissions for the newly created ShinyApps directory.
The Makefile
The Makefile provides the user with an easy way to execute the Docker commands required to build the Docker image and run the Docker containers. The make run
command is below:
run: build
docker run -d -p 8787:8787 -p 3838:3838 \
-e DISABLE_AUTH=true \
--name='gapminder-02-ct' \
-v ${HOME}:/home/rstudio/hostdata \
gapminder-02;
sleep 3;
firefox 127.0.0.1:8787;
firefox 127.0.0.1:3838/users/rstudio;
-d
runs the container in detatched mode-p 8787:8787
binds port 8787 on the container to port 8787 on the local computer for RStudio Server-p 3838:3838
binds port 3838 on the container to port 3838 on the local computer for Shiny Server-e DISABLE_AUTH=true
means that you don’t have to log into RStudio Server-v ${HOME}:/home/rstudio/hostdata
binds the home directory on the local computer to an accessible location within the Docker container.firefox 127.0.0.1:8787
this will open RStudio Server in firefox on linux, on a Mac replacefirefox
withopen
.firefox 127.0.0.1:3838/users/rstudio
this will open Shiny Server in firefox on linux, on a Mac replacefirefox
withopen
.
The other commands in the Makefile are convenience commands to start, stop and delete containers.
This approach of exposing both RStudio Server and Shiny Server allows a user to not only view the Shiny App, but to also use RStudio to explore the code in more detail and potentially make changes.
Deploying a Shiny app
There is also a make deploy
command:
deploy: build
docker run -d -p 9001:3838 \
-e DISABLE_AUTH=true \
--name='gapminder-02-deploy' \
gapminder-02;
sleep 3;
firefox 127.0.0.1:9001/users/rstudio/plot-app/;
This command only exposes the Shiny Server endpoint on port 9001 also jumps straight to the plot-app
Shiny app. This command could also be used to deploy the Docker image as a service, for example using MS Azure App Services or on a Kubernetes cluster.
Conclusions
This blog post has provided a basic template for Dockerizing a shiny app so that it is portable and relatively reproducible. This approach allows a Shiny app and its dependencies (and an RStudio Server to modify the app) to be shared between colleagues with only a minimal understanding of Docker and the command line required. It also sets the foundation for the Shiny app to be deployed as a Docker container service, for example using MS Azure App Services or equivalent services from Amazon Web Services or Google Cloud Platform.