Over the last couple of months, I’ve been running a Shiny app at shinyapps.io to model COVID-19 reproduction number. It has has a couple of hiccups recently. A couple of weeks ago it started running out of memory; the free tier of shinyapps.io limits apps to 1GB memory. With some judicious pruning, I got the app below this limit. This was fine until this weekend, when it again ran out of memory.
The main use of memory, after profiling, was the R0 estimate.R function. I can see no way of reducing memory use further without unravelling the R0 package.
Instead, I’ve decided to host the explorer as a Docker container inside Google Cloud Run. The latter is an interesting recent addition to the Google Cloud platform that allows one to deploy Docker images and map them to endpoints.
To create the Docker image I followed the excellent instructions by Björn Bos which can be found here. Here is a summary of the whole process:
- create a Dockerfile
- add shiny-server.sh and shiny-server.conf files
- build the docker image & test it locally
- upload it to Google Cloud Run
- Create a service in Google Cloud Run using that container
Everything went fine until step 5! The app deployed and started running ok; however static resources like bootstrap would not load — they were reported as failed with a 400 error in the browser console. It turns out that WebSockets are not supported on Google Cloud Run.
In order to get it to work I needed to disable various protocols in shiny-server.conf:
disable_protocols websocket xdr-streaming xhr-streaming iframe-eventsource iframe-htmlfile xdr-polling iframe-xhr-polling;
and include the httpuv package:
RUN R -e “remotes::install_github(c(‘rstudio/httpuv’))”
Once these changes were made and redeployed the app started working properly. I made sure to give it enough memory: I selected the 2GB option, which is ok for now. You can see the result here.
Overall the process was pretty painless. It took maybe five minutes to build the Docker image the first time as it set up R and installed the required packages. I had to make a couple of tweaks to the Docker file:
- my app didn’t live in a folder called app, rather it was called COVID19Explorer
- I had to give shiny-server.sh executable permissions
Otherwise, I followed Björn’s instructions exactly. The instructions for uploading to Google Cloud Run are here.
All the code is available on GitHub.