Running Shiny Server in Docker

Peter Solymos
Peter Solymos
Running Shiny Server in Docker
Table of Contents
Table of Contents

The dockerized Shiny Server is a heavyweight hosting option that plays an important role in the Shiny hosting landscape.

We looked at best practices for R with Docker where we compared four commonly used parent images. It was common in these images that these all contained a "local" Shiny app using shiny::runApp(). A special breed of dockerized Shiny apps is when the Shiny Server is running inside the Docker container. In this post, we'll explore this "dockerized Shiny Server" setup and discuss the pros and cons.

The files from this post can be found in the analythium/covidapp-shiny GitHub repository, inside the 99-images folder.

A simple Shiny app to display and forecast COVID-19 daily cases - analythium/covidapp-shiny

The Dockerfile

The parent image of the Dockerfile is rocker/shiny. This image is part of the Rocker project and is based on the versioned Ubuntu line of R images. It contains a versioned R installation, Shiny Server Open Source. It already has the shiny user defined and port 3838 exposed.

Shiny Server running inside a Docker container

On top of the parent image, you can follow the same pattern that we used for other base images: install system dependencies, install R packages, copy files for the Shiny app. The Shiny app goes inside the /srv/shiny-server/ folder where you can have more than one shiny app in different folders. You may also copy HTML files to provide navigation for your users.

We'll copy the files for the COVID-19 app, change the user to shiny (the EXPOSE directive is not needed but I left it there as a reminder). Finally, we define the command as /usr/bin/shiny-server to start the Shiny Server:

FROM rocker/shiny:4.0.5

# Install system requirements for index.R as needed
RUN apt-get update && apt-get install -y \
    --no-install-recommends \
    git-core \
    libssl-dev \
    libcurl4-gnutls-dev \
    curl \
    libsodium-dev \
    libxml2-dev \
    libicu-dev \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

COPY /etc/R
RUN install2.r --error --skipinstalled \
    shiny \
    forecast \
    jsonlite \
    ggplot2 \
    htmltools \

COPY ./app/* /srv/shiny-server/

USER shiny


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

The Docker image

I used the Docker BuildKit as explained before, then tested the image. Here is the script for your to replicate:

export IMAGE="analythium/covidapp-shiny:shiny"
export FILE="Dockerfile.shiny"
DOCKER_BUILDKIT=1 docker build --no-cache -f $FILE -t $IMAGE .
docker run -p 8080:3838 $IMAGE

Here is how build times and image sizes compare across the five images:

Parent image Parent size (GB) Final size (GB) Bild time (min)
rhub/r-minimal 0.035 0.222 27.0
rocker/r-base 0.761 1.050 2.9
rocker/r-ubuntu 0.673 1.220 3.1
rstudio/r-base 0.894 1.380 3.1
rocker/shiny 1.380 1.610 2.3

Build time was comparably small for all the other non-Alpine images, however, the size of the parent and the final images were the largest among the 5 different options.

Here are some thoughts to consider when using the rocker/shiny parent image to host a containerized Shiny applications.

You can run multiple Shiny apps over the same port exposed by Docker. The Shiny Server configuration allows you to disable the websocket protocol, this way you can host your apps in Container-as-a-Service environments, like Google Cloud Run, etc. This is achieved by using SockJS under the hood that can emulate websocket connections.

However, the image size is the largest among the comparable options. If the image includes multiple apps, those apps are not isolated, and managing their dependencies might become problematic over time.

An alternative use case for the rocker/shiny image is to host Shiny apps that are not copied into the image. This is done by mounting the app folder as a volume to the container (that is a live instance of the image) as explained on the Docker Hub page.

The next command adds two volumes, one with the apps and one for the Shiny Server logs in a -v host:container  fashion. The directories on the host will be created if those don't already exist.

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

This setup can be especially useful for hosting Shiny Apps in a Windows environment. You will need to add dependencies using the RUN directive.


The dockerized Shiny Server is a heavyweight option for hosting a single app, but it plays an important role in the Shiny hosting landscape. It allows you to run Shiny apps in unusual situations, like on Windows, or hosted container platforms.

Further reading

Great! Next, complete checkout for full access to Hosting Data Apps
Welcome back! You've successfully signed in
You've successfully subscribed to Hosting Data Apps
Success! Your account is fully activated, you now have access to all content
Success! Your billing info has been updated
Your billing was not updated