knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  fig.path = "man/figures/README-",
  out.width = "100%"
)

renv2docker

Lifecycle:
experimental CRAN
status

Project-specific cache of {renv} dependencies in Docker workflows

Motivation

Past me:

  1. I wanted to use {renv} in combination with Docker and didn't yet know how to mount my local {renv} cache, so the build process took much longer than I was willing to wait ;-)

  2. This also happened at a time before rocker switched to Ubuntu as the underlying Linux OS (Thanks to Eric Nantz for pointing that out in your podcast!).

    Before that (AFAIU and AFAIR), it could happen that the compilation process slightly differed between Ubuntu and Debian(?). So even though you might have properly mounted your local {renv} cache so it was available at build time, the resulting builds might have been incompatible with your local Linux OS.

    To be honest, I'm not sure how much of this still holds/is necessary after the switch to Ubuntu, but I nevertheless liked the idea of having an {renv} cache that is completely project-specific, so I continued building this package out.

    [TODO: Investigate the rocker history, etc. so I don't tell incorrect stuff here ;-)]

So I wanted to have a faster build experience and came up with this two-step approach:

STEP 1

Build an image that handles all of my package dependencies.

It only builds the dependencies once or when it has to (that is whenever my renv.lock is updated) and caches them back to a subdirectory within my local package directory (./renv/cache_docker [TODO: or was it ./renv/cache --> review this]) for future builds.

I called this image the Dependency Cache Manager (DCM).

STEP 2

Build the actual image

This image get access to the locally persisted {renv} cache from the previous step as well as ./renv/local (the place where your package's .tar.gz file is built to when you use the build.R; see below).

It calls renv::restore() which uses the cache and restores your package by installing it from source.

Installation

remotes::install_github("rappster/renv2docker")

Usage

library(renv2docker)
  1. Create the necessary environment variables for Docker
write_env_vars()

Technically, they are mostly used as ARGs instead of ENVs, but at least for PACKAGE_PORT it would make sense to pass it on as e ENV. Still learning about the nitty-gritty details ;-) See Docker ARG, ENV and .env - a Complete Guide for more details on this

  1. Generate ./Dockerfile and ./renv/Dockerfile
dockerfile <- use_template_dockerfile(open = FALSE)

readLines(dockerfile) %>% cat(sep = "\n")
dockerfile <- use_template_dockerfile_dcm(open = FALSE)

readLines(dockerfile) %>% cat(sep = "\n")
  1. Generate build.R

This template ensures that your package is built into ./renv/local and that all workflow requirements of renv2docker are met regarding the caching of package dependency builds.

build_r <- use_template_build(open = FALSE)

readLines(build_r) %>% cat(sep = "\n")
  1. Generate docker_build.sh and docker_run.sh
build_build_sh <- use_template_docker_build(open = FALSE)

readLines(build_build_sh) %>% cat(sep = "\n")
docker_run_sh <- use_template_docker_run(open = FALSE)

readLines(docker_run_sh) %>% cat(sep = "\n")
  1. Modify the desired R script to be run inside the Docker container

Find line

COPY inst/main.R main.R

and line

CMD Rscript 'main.R'

and adapt it to your setup.

The default setup

Open a terminal/shell within your package/project root directory and type

./docker_build.sh
  1. Run your Docker container
./docker_run.sh

Shout outs

This package was inspired and influenced by

My goal is to align this package as much as I can with existing workflows and best practices around R in combination with Docker.

TODOs

DISCLAIMER

This is another one of my "scratch your own itch" type of projects.

I use Linux (Pop!_OS) and hence aligned {renv} and Docker workflows to that platform --> not sure how much of it is applicable for MacOS or Windows

Still hope it works for other developers out there as well :-)

Code of Conduct

Please note that the renv2docker project is released with a Contributor Code of Conduct. By contributing to this project, you agree to abide by its terms.



rappster/renv2docker documentation built on Dec. 22, 2021, 12:57 p.m.