Running RStudio Server in a rootless Podman container

01/15/2023

Using R on Linux (especially if run a rolling-release distro like Arch or Void) can become very problematic, and time and energy consuming. The reason for that is by default, when run on Linux, R does not use binary packages. This means that every time you want to install a package, it will download the source code, and if there are any (C or C++) binaries that the package needs to work, it will compile them locally using GCC.

This can take a very long time (depending on your CPU), and installing a large package collection like tidyverse can take something like 30 minutes, and randomly fail because your system did not have some development headers installed.

The reason for this is the fact that the ABI for Linux userland may not be as stable as people want it to be, so some packages may simply stop working because they were compiled against an older version of some library. Windows (and probably macOS) users do not have this problem, as Windows’ ABI is famously stable (seriously, you can still run binaries from 1998 on a modern PC with Windows 11).

However, Posit (the people behind RStudio) have found a solution to this problem: they precompile the entire CRAN for a small number of stable versions of stable distros. Then, they will publish a list of OS dependencies as a shell script that will install all the necessary packages, and create a binary CRAN repository that you can pull the binary packages from if you use one of the supported distros.

The problem with this is that you will have to run a stable distro, like RHEL and friends, or Ubuntu LTS, which is fine, but often you either simply want to run an unsupported distro, or simply need some of the newer packages that are only available on less stable distributions.

There, however, is a relatively easy solution to work around this problem: you can run a stable distro in a container, together with all the possible CRAN dependencies, R and RStudio. The only problem is that running GUI applciations in containers is not really portable, breaks security, and can itself break at any moment, especially if you use Wayland. The workaround for this is to run the server version of RStudio inside the container, and then simply connect to it using a browser.

This comes with another free benefit: when you use R, you often run other people’s code, and containers provide a nice sandbox that will be able to contain the damage if some of the packages of some of the code that you run decide to go rogue. Because of this, running this in Docker can become problematic too, as Docker runs as root by default.

I worked around this problem by using Podman, a daemonless container engine that can run without root privileges at all. Depending on the distro you use, you might need to install is. Here is the package for Arch, it should be installed by default in Fedora, and in Ubuntu you can easily install it with:

sudo apt install podman

Now, R is open source, but RStudio is not, and you cannot simply redistribute its package files or container images containing RStudio. However, you can redistributefiles that will automate this download and installation process. You can find the needed files here: https://github.com/x0wllaar/RStudio-Container.

To install build the container you can simply clone the repo and do:

podman build -f ./Containerfile -t rstudio-container

This will automatically download the latest verisons of R and RStudio (4.1.3 and 2022.12.0-353 as of now), all the needed CRAN dependensies, install everything and automatically configure R to use the binary repo. The build process can take some time, and the resulting image will be around 6GB in size.

After the image has been built, you can create an ephemeral container using thins image like this:

podman run --rm -it \
    -p 127.0.0.1:8787:8888 \
    -v "$(realpath ./packages):/rlibrary:rw,Z" \
    --mount "type=volume,source=rstudio-config,destination=/root/.config,rw" \
    -v "$(realpath .):/host:rw,Z" rstudio-container

Please note the forwarding of 2 host folders to /rlibrary and /hosthome and a volume mount to /root/.config.

If everything went well, the container should run, and it should show a diagnostic message from RStudio Server on the terminal. Now, you can connect to the server inside the conatiner by going to http://127.0.0.1:8787 with your browser of choice.

Now, the container is ephemeral, so to get installed packages and configs to persist, and to access actual project files, we will need some podman tricks.

First, we will mount a folder on the host to the /rlibrary directory in the container. Then, we can instruct R to use this folder to store its package library. The mounting step was done by the podman run command above. To tell R to use the directory as the library, we can run in the R console in the browser:

.libPaths(c("/rlibrary", .libPaths()))

After this, all library() and install.packages() calls will use this directory. This needs to be done every time you restart the container, but this allows for per-project libraries and other very neat things.

Accessing the actual project files from the container is done via the /host directory, that should be bould to the project folder by the podman run command. You can then change into this directory using setwd() or via the file browser in RStudio.

In this container, install.packages() will automatically use the latest CRAN build (for RHEL 9) from Posit, so it should work very fast, and still use the latest version of all packages.

One notable issue with this approach, however, is the fact that LaTeX is not that easy to use. You can install TinyTeX but you will need to run

tinytex::install_tinytex(force=T)

every time you restart the session. This probably can be worked around by mounting more volumes and setting environment variables correctly, but I didn’t bother beacuse I don’t need LaTeX from R all that much.

In general, I think that this approach finally brings the usability of R on Linux closer to what people have on Windows and macOS, where you can just use install.packages() without having to go for lunch.

If something does not work, or if you need to update a version of R/RStudio in the container, feel free to open an issue on GitHub or to email me and I will try my best to help.