My Home RStudio Setup

Docker
Rocker Project
R
RStudio
Linux
Author

Tyler Clark

Published

September 7, 2022

When I am working on, well, work-related work, I use my company-issued laptop with Windows, Microsoft Office tools, and an installation of RStudio Desktop.

Recently I have been wanting to setup a personal installation of RStudio on my home file server as well. The main reasons being that RStudio makes for a great general-purpose IDE, and I’ve been wanting to start working with Quarto on some things, so right now seemed like a great time to figure it out.

Backstory

I wrote in a previous post that I am working on making my home file server more stable, which means moving more of the userland packages to containers. Most of the programs I use on that PC (Firefox, VLC, Gimp, etc.) all have flatpaks that work quite well for me.

However, R and RStudio are not in that category. On Debian, both require going outside of the official Debian repositories: R has a repository for up-to-date versions, while RStudio does not (although they do provide binary downloads). Add to that the system dependencies of some packages and now there are random libraries installed all over, with no dependency chain in apt. There is the option to use the Debian packages from the CRAN repository, but those are not complete and have given me issues in the past, as far as permissions, updates, etc.

It seemed to me that R would need it’s own environment. How best to do that? I turned to Docker for this particular case.

Docker

Docker Setup

Base Image

Luckily, smarter people than myself have already thought about this and started the Rocker Project. They have many different containers all built in layers on each other so it’s easy to find a good starting point for running R/shiny apps, or building a general dev environment like I was looking for.

Adding on Layers

At the time of this post I chose the rocker/tidyverse image to build my RStudio environment, but this could change in the future (see my repo for the latest).1 Having Rstudio server and the tidyverse packages gets me 90% of the way to where I want to be, but there are other packages that I use quite a bit. To get those packages I would either need to

  • Option 1:
    • Spin up an image,
    • Download the packages in the image
    • Save that modified environment as a new image via docker commit
  • Option 2:
    • Create a Dockerfile and let docker build handle it

I am a big fan of keeping things simple, reproducible, and mostly in line with the intended workflow (sometimes rules are made to be broken, but I am not familiar enough with docker to be getting my hands that dirty just yet), so I went with Option 2.

Configuration

At the time of this post, this is my Dockerfile:

FROM rocker/tidyverse:4.2.1
COPY packages.R /home/rstudio/packages.R
RUN R -q -e "source('/home/rstudio/packages.R')" \
    && rm -rf /tmp/* \
    && strip /usr/local/lib/R/site-library/*/libs/*.so

I start with the rocker/tidyverse:4.2.1 image, then copy an R script into the rstudio home directory:

install.packages(
         c(
           "markdown",
           "gt", 
           "DT", 
           "kableExtra", 
           "flextable", 
           "huxtable", 
           "reactable", 
           "formattable", 
           "pixiedust", 
           "agricolae", 
           "car"
         )
)

After the script is run, I execute 2 more commands to clean up the image (as advised by the Rocker team). This image is available on Docker Hub as tclark89/tidyverse-extra

One day I may dig more deeply into setting up my own very custom image by building something more from scratch, but for now the rocker/tidyverse image works as great jumping-off point.

Compose

Now that the image has been created it needs to be spun up, and it needs to be run with certain parameters. The best way to do that is with a docker-compose.yml file. Currently mine looks like this:

services:
  rstudio:
    image: tclark89/tidyverse-extra:4.2.1
    ports: 
      - "8787:8787"
    environment:
      PASSWORD: rstudio
      ROOT: true
    volumes:
      - ~/.config/rstudio:/home/rstudio/.config/rstudio
      - ~/.local/share/rstudio:/home/rstudio/.local/share/rstudio
      - ~/code/R:/home/rstudio/workspace

The docker-compose.yml file starts the rstudio service:

  • Uses my custom docker image as the base

  • Maps the container ports

  • Sets the rstudio user’s password and gives it sudo via environment variables

  • Maps some directories to be shared between host and container. This lets settings and files persist in my /home directory between sessions.

The rocker team provides an example compose file as well.

Running the Container

All it takes to run the docker container now is to cd to the directory with the docker-compose.yml file and issue the command: docker compose up. However, I would like for this to happen automatically so I can just login and go. There may be a different way to do this, but I went with a systemd service file.

After some digging through the Arch Wiki and various SO posts I settled on the following:

[Unit]
Description=%i service with docker compose
PartOf=docker.service
After=docker.service

[Service]
Type=oneshot
RemainAfterExit=true
WorkingDirectory=/home/%u/docker/compose/%i
ExecStart=/usr/bin/docker compose up -d --remove-orphans
ExecStop=/usr/bin/docker-compose down

[Install]
WantedBy=multi-user.target

This service file is a user @.service, so the file is named docker-compose@.service and called via:

systemctl start --user docker-compose@tidyverse-extra.service

or for a persistent setup:

systemctl enable --now --user docker-compose@tidyverse-extra.service

Because docker compose looks for a docker-compose.yml file in the working directory, I needed to specify one in this file and make sure that directory existed in my /home. The %u makes this file user-agnostic and the %i and @ make it usable for any other docker service I may decide to use later. I just need to make sure that I create a directory in ~/docker/compose/ and put the docker-compose.yml file there.

As a final note, this will only work if your user is part of the docker group, otherwise docker needs root privileges. This file could just as easily be made to work as root, but the docker-compose.yml file would need to have absolute paths instead of user-relative ones.

Update: 11/7/2022

Docker doesn’t recommend making images persistent with systemd files. There is a built-in method for starting containers at boot:

  1. Start the container with docker run, docker compose up, etc.
  2. Run the command: docker update --restart unless-stopped $container_name

Much simpler!

Using RStudio

Now that all of the pieces are in place, all I have to do to access RStudio at home is to open a browser, access my file server at port 8787, and log in to RStudio Server. Then I can just git pull and get back to work on this website or whatever project I am focused on.

For now this all works wonderfully. I don’t have to muck around with dependencies on my server, and saving the docker files to GitHub and the image to Docker Hub means that it should be reproducible in case I can’t access the server. For instance, if I am away from home but want to work on a project I can spin up the docker image directly on my Chromebook (via the built-in Linux VM) and fire away. In fact, you can even run this image in a browser via Play with Docker, though it eats up quite a bit of RAM to do so.

Footnotes

  1. Update (10/12/2022): I have switched my main docker image to rocker/verse (for LaTeX) and set up a new github repository here↩︎