Dev containers with R and Quarto
My favourite new trick is setting up a reproducible R/Quarto development environment in two clicks. It looks like this, and creating it yourself is as simple as following a link:
Basic 2-core Codespaces like the one here are free to use for 60 hours a month for everyone with a GitHub account (as of March 2023)âenough to do 3 hours of work every workday.
You wonât be billed you unless you add a billing method and raise the spending limit, and unused Codespaces stop running after half an hour if you forget to stop them yourself. So give it a whirl!
We publish a lot of open data analyses at 360info. We want to make visuals quickly and easily accessible to journalists, but we also want the underlying data, and any analysis weâve done to it, reproducible too. I call it a âcake and ingredientsâ modelâwe want to deliver both.
So we want people to be able to dive into our analysis quickly, rather than floundering installing R packages or GDAL or something.
Development containers, or dev containers, donât just control dependencies like R package versionsâthey make your analysis shareable, too! Theyâre real easy to set up and share, even if you havenât messed around with Docker before.
Wait, whatâs a dev container again?
When you boot a project up in a dev container, your project folder on your laptop (the host) is mounted inside a Docker containerâa sandboxed Linux environment with tools that you specify. The container might be as simple as just a fresh copy of Linux, or it might have R and a bunch of packages you specify installed.
Dev containers build on the strengths of Docker containers by making them the place you do your development work. When you use a dev container, VSCode brings your usual extensions, themes and keyboard shortcuts along for the rideâeven magical extensions like Live Share.
The dev containerâs specificationâthe thing that tells it which tools, languages and packages to includeâstays with the project, so everyone using the project gets the same environment (no matter how they have VSCode itself set up). They can recreate it on their laptop if they have Docker installed⊠or they can run it in the cloud with GitHub Codespaces.
Okay, so how do I set one up?
If you want to run dev containers on your own laptop, the one thing youâll need to install (apart from VSCode itself) is Docker. Luckily, you donât need Docker experience to use dev containersâVSCode handles the tricky bits.
The magic happens in the .devcontainer/devcontainer.json
file. Open a folder in VSCode that has a .devcontainer
folder with devcontainer.json
in it, and VSCode will prompt you to reopen the project in a dev container.
If youâre starting from scratch and need to work out which tools you want, VSCode has a wizard available from the command palette that can write this file for you. You choose the language you primarily want to work in, add extra features, and off you go!
Or you can write it yourself. Hereâs the devcontainer.json
I usually start with on R/Quarto projects:
.devcontainer/devcontainer.json
{
"name": "R (rocker/r-ver base)",
"image": "ghcr.io/rocker-org/devcontainer/r-ver:4.2",
"features": {
"ghcr.io/rocker-org/devcontainer-features/quarto-cli:1": {
"version": "prerelease"
},
"ghcr.io/rocker-org/devcontainer-features/apt-packages:1": {
"packages": "libudunits2-dev,libxtst6,libxt6,libmagick++-dev"
},
"ghcr.io/rocker-org/devcontainer-features/r-packages:1": {
"packages": "github::rstudio/renv,tidyverse,here,httpgd"
},
},
"customizations": {
"vscode": {
"extensions": ["mechatroner.rainbow-csv"]
},
"codespaces": {
"openFiles": ["README.md"]
}
}
}
Letâs break this spec down:
Weâre going to use an R
image
published by the community. It uses the latest R 4.2.x releases.We can add extra
features
to the image:The pre-release version of Quarto at the time gets installed (you can also specify a fixed version), and the Quarto VSCode extension is added.
Four packages are installed from APT, the Ubuntu package manager.
A few R packages are installed. Most are from the Posit Package Manager (PPM), which acts as a CRAN mirror, but
renv
is installed from GitHub here.
Finally, we add a few editor-specific
customizations
:In addition to the R and Quarto VSCode extensions, which come with the image and features, I want to make sure that the Rainbow CSV extension is installed. Itâs a nice, lightweight colouriser for CSV files.
When someone is launching this project as a Codespace (more on that below!), we can tell the container to open a set of files by default. This is a great way to welcome users by automatically opening the README or an intended entrypoint to the project.
Once youâre ready to launch your dev container, press Shift-Ctrl-PShift-Ctrl-P to open the command palette, and select Dev Containers: Reopen in Container. Hold on!
Once youâre working inside the container, you can write code, save files, commit and push as usual. For the most part, VSCode brings your usual git credentials into the container.
I use 1Passwordâs SSH agent, and I havenât quite figured out how to make that work with dev containers yet. It feels like a solvable problem, though.
You can close the container when youâre done, and itâll open right back up next timeâor if you delete the container, it can be recreated from the container spec.
You can install tools and packages from the terminal once youâre inside the container if you like, but keep in mind that the changes wonât persist if you delete the container (or if someone else is trying to use it).
Itâs generally best to specify tools you want in the container in devcontainer.json
.
Is it really reproducible?
Nothingâs completely reproducible, and dev containers certainly arenât foolproof. A few things to keep in mind:
If you use Rockerâs
apt-packages
feature to install other tools, these track whatever the latest versions are on APT, as far as Iâm aware. If you need fixed versions of things, either:- look for dev container features for those tools (eg. use the
node
feature to install a fixed version of npm), or- install those tools manually using a
postCreateCommand
- install those tools manually using a
- look for dev container features for those tools (eg. use the
The version of R is determined by the version of the
image
you select. If you selectlatest
or the latest R minor version (currently4.2
), it will track the latest patch version (eg.4.2.3
) until a new minor release comes out. The Rocker dev containers donât have labels for specific patch versions.The versions of R packages that come from the PPM are also determined by the
image
you select. If you selectlatest
or the latest R minor version (currently4.2
), the container will use the latest available versions (even if those versions have changed since you last built the container). Once a new minor version releases, previous ones will switch to using a fixed date checkpoint on the PPM.If you need to make sure that R package versions do not change from the start of your analysis, you can set a specific Posit Package Manager checkpoint even for the latest R image using:
"containerEnv": { "PKG_CRAN_MIRROR": "https://packagemanager.posit.co/cran/2023-01-31" },
For reproducibility reasons, I generally I find it easier to start a project working in a dev container, rather than converting an existing project. You can use renv
to restore from an renv.lock
file, or even share an renv cache across several dev conainter projects, but Iâve found all that a little difficult in practice.
On the other hand, if you start in a dev container from the beginning and set a fixed PPM checkpoint, you know that your R dependencies wonât change.
You can also use Miles McBainâs helpful {capsule}
package to quickly write out a lockfile. Other folks can use that to install R packages even if theyâre not sold on using a dev container.
Why now?
Dev containers have been around for a year or two, but Iâve leapt on them now because the R community are now producing cross-platform images that include Quarto support.
That means it doesnât matter whether youâre in a Codespace, on a Windows laptop or using an Apple Silicon Macbook: the code should run just the same regardless.
I also donât exclusively code in R. Quartoâs VSCode support is first-class, whether youâre coding in R, Python, Julia or Observable JSâand I can add any number of other languages with the confidence that VSCode will handle them the same way it does locally.
Dev containers have a whole bunch of exciting applications. Hereâre just a few:
- Workshops, livestreams and reproducible live talk demos
- Demos for analysis packages
- Reproducible open source journalism
Give âem a try!