Deploying Shiny App with Docker

shiny
docker

#1

Hey everyone,

I am attempting to deploy a Shiny app on AWS (Ubuntu 16.04) with Docker. I have successfully launched the app with Shiny Server, but need to containerize the app for portability. So far I have a Dockerfile that looks like this:

FROM rocker/shiny:latest

#adds server.R, ui.R, and source files to project directory
ADD . /srv/shiny-server/app_energy

#loads necessary packages
RUN sudo R -e "install.packages(c('shiny', 'dplyr', 'plotly', 'magrittr', 'ggplot2', 'lubridate'...))"

EXPOSE 3838

CMD ["/usr/bin/shiny-server.sh"]

To start the app I run:

docker run --rm -p 3838:3838 energy

or:

docker run --rm -p 3838:3838 \ 
    -v /srv/shinyapps/:/srv/shiny-server/ \
    -v /srv/shinylog/:/var/log/shiny-server/ \
energy

The first gives me the old faithful:

ERROR: An error has occurred. Check your logs or contact the app author for clarification.

While the second gives me a ‘page not found error.’ I have not been able to successfully glean any log files.

Any thoughts or tips? All help is greatly appreciated.

Thank you,

Kiefer Smith


#2

Hi Kiefer,

I’ve run into this precise issue many times.

A log file will be created for each R process when it is started. However, if a process closes successfully, the error log associated with that process will be automatically deleted. The only error log files that will remain on disk are those associated with R processes that did not exit as expected.

To force the preservation of the log file, try creating a custom shiny-server.conf file and include the following line to the top of the file: preserve_logs true;

In your docker file add this file to the following location on the container: /etc/shiny-server/.

Now you should have your log file preserved!

Best,

Bethany Yollin


#3

I have a walk through for deploying a Shiny app on Google Cloud Platform that you could perhaps adapt for AWS, at least the Dockerfile - guide is here. If you don’t mind using GCP then there are a lot of helper functions to help too, such as gce_shiny_addapp()

Those Shiny apps are launched via a startup script (cloud config here) that is below:

docker run -v /home/gcer/library/:/library/ \
                                  --name=shinyserver \
                                  -p 80:3838 \
                                  -v /home/gcer/shinyapps/:/srv/shiny-server/gcer/ \
                                  -v /home/gcer/shinylog/:/var/log/ \
                                  your-docker-container

Note putting the port on 80 (web) that may be useful, and where to put the logs.

A working Dockerised Shiny app demo is in the repo here

The logs are either in the volume you link to the logs within the Docker, or a good debug is to log into the Docker container via docker exec -it dockername bash which puts you in a shell within it, if its running. The logs you can browse to /var/log/shiny-server

Otherwise, if the docker image crashed on startup you can see via journalctl -u docker.service to get an idea of what caused the crash, although it sounds like your Shiny is running.

Its probably either the ports not being opened (in which case mapping to port 80 will fix it) or you haven’t the expected dependencies in your Dockerfile. For that, I recommend containerit which you can point at your Shiny script and it will work out the dependencies for you and write your Dockerfile for you. Its magic.

Yours sincerely,
Mark


#4

I think the other comments address your problems. One bit of advice I think should be mentioned is that using the : latest tag from docker images may not always be desired. If you plan to have your shiny app be long live without maintenance, I would peg it to a specific version. Specifically, I would copy the Dockerfile from the rocker/shiny repo and change the first line

FROM r-base:latest

To

FROM r-base:3.4.1

And the lines that install the shiny server version based on a script,

wget --no-verbose https://s3.amazonaws.com/rstudio-shiny-server-os-build/ubuntu-12.04/x86_64/VERSION -O "version.txt" && \
    VERSION=$(cat version.txt)  && \
    wget --no-verbose "https://s3.amazonaws.com/rstudio-shiny-server-os-build/ubuntu-12.04/x86_64/shiny-server-$VERSION-amd64.deb" -O ss-latest.deb && \

To reference a specific version, like

wget https://download3.rstudio.org/ubuntu-12.04/x86_64/shiny-server-1.5.5.872-amd64.deb

Clearly there is a bit more work to do, but being explicit of whatever version of R and shiny server you need help towards ensuring future updates don’t cause your shiny app to stop working.

If you don’t like how long that makes the Dockerfile, you could fork the rocker/shiny repo and pin a version, then use FROM myshinyfork


#5

Thanks for this! I am now getting log files which is immensely helpful.


#6

Thanks to everyone who posted tips.

I did finally get the app running properly in a container. I think the main issue was that I didn’t fully understand Docker. I think the main thing I had to realize is that a container is a completely empty filesystem.