Working with renv (Virtual Environment) and Docker for Shiny Apps

Hello shiny developers,

As you see the example Dockerfile below, third RUN layer installs R packages. If you have to work many R packages for the apps, the installation of all packages takes too much time at this step.

I thought if we have a virtual environment for our project, we can skip this layer without wasting too much time. That’s why, I looked at renv package to create a virtual environment and implement it into a Dockerfile.

I arrange the docker file like on the documentation. However, I run the container and it doesn’t read all libraries from virtual environment I created , it reads the package list from lockfile and starts downloading and installing all packages step by step I need.

The Example Dockerfile in the Documantation

FROM openanalytics/r-base

LABEL maintainer "Tobias Verbeke <tobias.verbeke@openanalytics.eu>"

# system libraries of general use
RUN apt-get update && apt-get install -y \
    sudo \
    pandoc \
    pandoc-citeproc \
    libcurl4-gnutls-dev \
    libcairo2-dev \
    libxt-dev \
    libssl-dev \
    libssh2-1-dev \
    libssl1.0.0

# system library dependency for the euler app
RUN apt-get update && apt-get install -y \
    libmpfr-dev

# basic shiny functionality
RUN R -e "install.packages(c('shiny', 'rmarkdown'), repos='https://cloud.r-project.org/')"

# install dependencies of the euler app
RUN R -e "install.packages('Rmpfr', repos='https://cloud.r-project.org/')"

# copy the app to the image
RUN mkdir /root/euler
COPY euler /root/euler

COPY Rprofile.site /usr/lib/R/etc/

EXPOSE 3838

CMD ["R", "-e", "shiny::runApp('/root/euler')"]

Dockerfile of my project

FROM openanalytics/r-base

LABEL maintainer  "Tobias Verbeke <tobias.verbeke@openanalytics.eu>"

# https://packagemanager.posit.co/client/#/repos/2/packages/A3
# system libraries of general use
RUN apt-get update && apt-get install -y \
    sudo \
    nano \
    make \
    automake \
    pandoc \
    pandoc-citeproc \
    libicu-dev \
    zlib1g-dev \
    libcurl4-openssl-dev \
    libssl-dev \
    libfontconfig1-dev \
    libfreetype6-dev \
    libfribidi-dev \
    libxml2-dev \
    libharfbuzz-dev \
    libjpeg-dev \
    libpng-dev \
    libtiff-dev \
    libglpk-dev \
    libgmp3-dev \
    libpq-dev \
    libcairo2-dev \
    libxt-dev \
    libssh2-1-dev \
    libssl1.1 \
    libmpfr-dev 
    
# install shiny packages
RUN R -e "install.packages(c('renv'), repos='https://cloud.r-project.org/')"

# Create Directory
RUN mkdir /root/Project

# copy the app to the image
COPY Project /root/Project

# copy all virtual environment files
COPY renv.lock renv.lock
COPY renv renv
COPY .Rprofile .Rprofile

EXPOSE 3838

CMD ["R", "-e", "renv::restore(); shiny::runApp('/root/Project')"]

Building Dockerfile and testing it

# Build the image from dockerfile I created
docker build -t 127.0.0.1:5000/renv/test .

# Run a container and check the shiny app. Does the image works or not?
docker run -p 4040:3838 127.0.0.1:5000/renv/test     

What is the best way to work with Virtual Environment and ShinyProxy and how we should have a dockerfile to make this?

Thanks in advance.

I probably don’t really get what you try to achieve but why don’t you add the renv::restore() step as a RUN command to your Dockerfile? You need to to that step only once you build the image - we do it like that and it works really nice.

hi,

you may find

golem::add_dockerfile_with_renv_shinyproxy()

usefull

even if it’s in french this article may https://thinkr.fr/deploiement-dune-application-shiny-dans-docker-avec-renv-et-golem/

Hi @prinn,

I already installed packages my Shinyapp needs. The packages are under renv/library directory locally.

However, renv:restore() re-downloads and re-installs all packages one by one instead of using package from local, when building a dockerfile. It takes too much time unfortunately.

How can I avoid redownloading and rebuilding the packages, when building a dockerfile? Is there any way to use installed R packages in renv/library locally?

Thanks in advance.

Interesting, I am thinking about how to deploy packages with renv in a Docker container also. While, this software is outside the scope of OpenAnalytics products, I figured it would be a good forum to discuss, and there it is already an open topic!!

I have been a proponent of renv for a while. For R programs it seems about the best, though still kind of geared towards a specific Posit workflow.

My problem I am trying to solve is that renv takes a long time to build libraries on occasion. In general this isn’t a problem, because renv creates local caches of the builds and most the time it is linking to the cache, though in practice renv still calls out to the repo to verify that the versions match. Last I recall there was no way to skip that step. I think that may answer your question. However, I am thinking about how to go about doing something similar and would like to see if anyone has an idea. The problem I am having is if I build the container on some service like ghcr.io, where I don’t have access to a local filesystem to store the cache and mount it. We already have a container that we use to derive our shiny apps, I figured I could create a cache in that, then have renv copy the files over maybe using renv::hydrate, and delete the cache to save space in the final build. Might be a better solution, but I would be curious if anyone has tried that before or had an idea about to quickly build lightweight R containers with renv.

1 Like