Skip to content

Instantly share code, notes, and snippets.

@KasperSkytte
Last active November 26, 2021 14:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save KasperSkytte/270ceb8bc19af7f3bd24c8f9f08f259a to your computer and use it in GitHub Desktop.
Save KasperSkytte/270ceb8bc19af7f3bd24c8f9f08f259a to your computer and use it in GitHub Desktop.
Run RStudio with a specific R version through a docker container with support for renv caching on host.
#!/usr/bin/env bash
set -eu
#set variables
r_ver="${r_ver:-"4.0.4"}"
image_name="${image_name:-"rstudio_r${r_ver}"}"
password="${password:-"supersafepassword"}"
port="${port:-"8787"}" #will generate a random one if unavailable
RENV_PATHS_CACHE_HOST="${HOME}/.local/share/renv/cache" #path to renv cache on host, renv default is ~/.local/share/renv/cache
RENV_PATHS_CACHE_CONTAINER="/usr/local/lib/R/renv-cache/" #path to renv cache within the container (dont have to change)
num_threads=$(($(nproc) - 2)) #all cores except 2
#done setting variables
#build the container image
echo "Creating temporary folder for the Dockerfile..."
tmpdir=$(mktemp -dt "rstudio_r${r_ver}_XXXXX")
pushd "$tmpdir" > /dev/null
#sensible default rstudio preferences
cat << rstudio-prefs > rstudio-prefs.json
{
"save_workspace": "never",
"always_save_history": false,
"reuse_sessions_for_project_links": true,
"load_workspace": false,
"initial_working_directory": "/",
"console_double_click_select": true,
"editor_theme": "Merbivore Soft",
"rmd_chunk_output_inline": false,
"hide_console_on_chunk_execute": false,
"posix_terminal_shell": "bash",
"real_time_spellchecking": false
}
rstudio-prefs
#dockerfile
cat << Dockerfile > Dockerfile
FROM rocker/rstudio:${r_ver}
#multithreaded make
ENV MAKEFLAGS="-j ${num_threads} "
#install nice-to-have system dependencies for R, and netstat to scan ports
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update -qqy && \\
apt-get install -y --no-install-recommends --no-install-suggests \\
libxml2-dev \\
libcairo2-dev \\
libxt-dev \\
libjpeg-dev \\
net-tools \\
libharfbuzz-dev \\
libfribidi-dev \\
libfreetype6-dev \\
libpng-dev
#set default renv cache path in container
#change CRAN mirror from https://packagemanager.rstudio.com to AAU mirror
#install renv, and install all packages in the lock file to /usr/local/lib/R/site-library/ in container
RUN echo "RENV_PATHS_CACHE=${RENV_PATHS_CACHE_CONTAINER}" >> /usr/local/lib/R/etc/Renviron.site && \\
R -e "install.packages('renv', Ncpus = ${num_threads})" && \\
R -e "renv::consent(provided = TRUE)"
#add rstudio-prefs.json
COPY ./rstudio-prefs.json /home/rstudio/.config/rstudio/rstudio-prefs.json
#enable users to install R packages
RUN chown 1000:1000 -R \\
/usr/local/lib/R/site-library \\
/usr/local/lib/R/library \\
/home/rstudio
#silence RStudio warnings about not being able to write dictionary stuff to /root
VOLUME /root
Dockerfile
docker build -t "${image_name}" .
echo "Removing temporary folder..."
popd > /dev/null && rm -rf "$tmpdir"
checkPort() {
randomPort() {
echo $(( ( RANDOM % 60000 ) + 1025 ))
}
local port
local check_port
check_port=${1:-"$(randomPort)"}
while [ -n "$check_port" ]
do
port="$check_port"
check_port=$(docker run --rm --net=host "${image_name}" netstat -atn | grep "$port" || :)
if [ -n "$check_port" ]
then
check_port="$(randomPort)"
fi
done
echo "$port"
}
port=$(checkPort "$port")
mkdir -p "${RENV_PATHS_CACHE_HOST}"
#launch the container with the host cache mounted in the container
docker run -d \
-e "PASSWORD=${password}" \
-e "RENV_PATHS_CACHE=${RENV_PATHS_CACHE_CONTAINER}" \
-v "${RENV_PATHS_CACHE_HOST}:${RENV_PATHS_CACHE_CONTAINER}" \
-v "$HOME:$HOME" \
-p "$port":8787 \
"${image_name}"
echo
echo "Launch RStudio through a browser at one of these adresses:"
echo "http://127.0.0.1:${port} (this machine only)"
for IP in $(hostname -I)
do
echo "http://${IP}:${port}"
done
echo
echo "Username: rstudio"
echo "Password: ${password}"
@KasperSkytte
Copy link
Author

KasperSkytte commented Jun 10, 2021

Also solves issue rstudio/renv#446 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment