R Shiny app in Docker using a conda environment

󰃭 2023-03-21

There are many ways of running a Shiny Server in a Docker container, for example using the rocker/shiny images.

However, this approach becomes more involved when one wants to run the Shiny server and apps with base R and additional packages from a conda environment using the conda-forge channel. The advantage here is that one can easily declare the used packages with version numbers in a conda environment file.

I am still trying to figure out a good way to run a full Shiny server from a conda environment in Docker, but found a nice minimal solution for running just a single Shiny app in a Docker container, without the need for a full Shiny server installation.

Setup

We need three main components: the Dockerfile, the conda environment definition and the code of the R Shiny app.

├── app
│   ├── app.R
│   ├── server.R
│   └── ui.R
├── conda-env.yaml
└── Dockerfile

Dockerfile

The Dockerfile is based on the mambaorg/micromamba image, which is extended by copying the Shiny app, which in turn is simply run via the shiny::shinyApp() function.

FROM mambaorg/micromamba:1.3.1
COPY --chown=$MAMBA_USER:$MAMBA_USER conda-env.yaml /tmp/env.yaml
RUN micromamba install -y -n base -f /tmp/env.yaml && \
    micromamba clean --all --yes

COPY --chmod=777 ./app/*.R ./

CMD ["/bin/bash", "-c", "./app.R"]

Conda environment

The conda environment using packages from the conda-forge channel is defined in a file called conda-env.yaml, for example like this:

name: base
channels:
  - conda-forge
dependencies:
  - conda-forge::r-base=4.2.3
  - conda-forge::r-tidyverse=2.0.0
  - conda-forge::r-shiny=1.7.4
  - conda-forge::r-shinyjs=2.1.0
  - conda-forge::r-dt=0.27
  - conda-forge::r-shinycssloaders=1.0.0
  ...

Shiny app

Finally, the Shiny app is contained in app/app.R, which in turn can include other files, e.g. ui.R or server.R in this example:

#!/usr/bin/env Rscript
library(shiny)

source("ui.R")
source("server.R")

options(shiny.host = '0.0.0.0')
options(shiny.port = 3838)

# Run Shiny app
shinyApp(ui = ui, server = server)

Build image and run container

For running the container on port 8001:

docker build -t docker-micromamba-shiny:latest .
docker run -d -p 8001:3838 docker-micromamba-shiny:latest

Open the app in the web browser at http://localhost:8001/.

Notes

  • The example source code from above is in this GitHub repository.
  • In contrast to a standard Shiny server that can host multiple apps at different URLs, the shiny app in this example runs at the root URL path.