diff --git a/registry/coder/templates/docker-rstudio/README.md b/registry/coder/templates/docker-rstudio/README.md new file mode 100644 index 000000000..98d60f88c --- /dev/null +++ b/registry/coder/templates/docker-rstudio/README.md @@ -0,0 +1,98 @@ +--- +display_name: Docker RStudio +description: Provision Docker containers with RStudio, code-server, and RMarkdown +icon: ../../../../.icons/rstudio.svg +verified: true +tags: [docker, rstudio, r, rmarkdown, code-server] +--- + +# R Development on Docker Containers + +Provision Docker containers pre-configured for R development as [Coder workspaces](https://coder.com/docs/workspaces) with this template. + +Each workspace comes with: + +- **RStudio Server** — full-featured R IDE in the browser. +- **code-server** — VS Code in the browser for general editing. +- **RMarkdown** — author reproducible documents, reports, and presentations. + +The workspace is based on the [rocker/rstudio](https://rocker-project.org/) image, which ships R and RStudio Server pre-installed. + +## Prerequisites + +### Infrastructure + +#### Running Coder inside Docker + +If you installed Coder as a container within Docker, you will have to do the following things: + +- Make the Docker socket available to the container + - **(recommended) Mount `/var/run/docker.sock` via `--mount`/`volume`** + - _(advanced) Restrict the Docker socket via https://github.com/Tecnativa/docker-socket-proxy_ +- Set `--group-add`/`group_add` to the GID of the Docker group on the **host** machine + - You can get the GID by running `getent group docker` on the **host** machine + +#### Running Coder outside of Docker + +If you installed Coder as a system package, the VM you run Coder on must have a running Docker socket and the `coder` user must be added to the Docker group: + +```sh +# Add coder user to Docker group +sudo adduser coder docker + +# Restart Coder server +sudo systemctl restart coder + +# Test Docker +sudo -u coder docker ps +``` + +## Architecture + +This template provisions the following resources: + +- Docker image (built from `build/Dockerfile`, extending `rocker/rstudio` with system dependencies) +- Docker container (ephemeral — destroyed on workspace stop) +- Docker volume (persistent on `/home/rstudio`) + +When the workspace restarts, tools and files outside `/home/rstudio` are not persisted. The R library path defaults to a subdirectory of the home folder, so installed packages (including RMarkdown) survive restarts. + +> [!NOTE] +> This template is designed to be a starting point! Edit the Terraform to extend it for your use case. + +## Customization + +### Changing the R version + +Set the `rstudio_version` variable to any valid [rocker/rstudio tag](https://hub.docker.com/r/rocker/rstudio/tags) (for example `4.4.2`, `4.3`, or `latest`). + +### Installing additional R packages + +R packages are pre-installed via the `build/Dockerfile` so they are available immediately when the workspace starts. To add more packages, add `install.packages()` calls to the Dockerfile: + +```dockerfile +RUN R -e "install.packages(c('tidyverse', 'shiny'))" +``` + +The image is pre-configured to use [Posit Package Manager](https://packagemanager.posit.co/) which provides pre-compiled binary packages for fast installation. Packages installed at build time avoid long startup delays from compiling from source on every workspace start. + +### Adding system dependencies + +The `build/Dockerfile` extends the `rocker/rstudio` base image with system packages required by modules (e.g. `curl` for code-server, `cmake` for R package compilation). If you add modules that need additional system-level tools, add them to the `Dockerfile`: + +```dockerfile +RUN apt-get update \ + && apt-get install -y \ + curl \ + cmake \ + your-package-here \ + && rm -rf /var/lib/apt/lists/* +``` + +### Adding LaTeX for PDF rendering + +RMarkdown can render PDF output when LaTeX is available. Add the following to the startup script to install TinyTeX: + +```sh +R --quiet -e "if (!require('tinytex', quietly = TRUE)) { install.packages('tinytex', repos = 'https://cloud.r-project.org'); tinytex::install_tinytex() }" +``` diff --git a/registry/coder/templates/docker-rstudio/build/Dockerfile b/registry/coder/templates/docker-rstudio/build/Dockerfile new file mode 100644 index 000000000..a600e748b --- /dev/null +++ b/registry/coder/templates/docker-rstudio/build/Dockerfile @@ -0,0 +1,12 @@ +ARG RSTUDIO_VERSION=4 +FROM rocker/rstudio:${RSTUDIO_VERSION} + +RUN apt-get update \ + && apt-get install -y \ + curl \ + cmake \ + && rm -rf /var/lib/apt/lists/* + +RUN R -e "install.packages('rmarkdown')" + +RUN echo "auth-minimum-user-id=0" >>/etc/rstudio/rserver.conf diff --git a/registry/coder/templates/docker-rstudio/main.tf b/registry/coder/templates/docker-rstudio/main.tf new file mode 100644 index 000000000..de86cda16 --- /dev/null +++ b/registry/coder/templates/docker-rstudio/main.tf @@ -0,0 +1,244 @@ +terraform { + required_providers { + coder = { + source = "coder/coder" + } + docker = { + source = "kreuzwerker/docker" + } + } +} + +locals { + username = data.coder_workspace_owner.me.name +} + +variable "docker_socket" { + default = "" + description = "(Optional) Docker socket URI" + type = string +} + +variable "rstudio_version" { + default = "4" + description = "The rocker/rstudio image tag to use (e.g. 4, 4.4, 4.4.2)" + type = string +} + +provider "docker" { + # Defaulting to null if the variable is an empty string lets us + # have an optional variable without having to set our own default. + host = var.docker_socket != "" ? var.docker_socket : null +} + +data "coder_provisioner" "me" {} +data "coder_workspace" "me" {} +data "coder_workspace_owner" "me" {} + +resource "coder_agent" "main" { + arch = data.coder_provisioner.me.arch + os = "linux" + startup_script = <<-EOT + set -e + + # Prepare user home with default files on first start. + if [ ! -f ~/.init_done ]; then + cp -rT /etc/skel ~ 2>/dev/null || true + touch ~/.init_done + fi + + # Start RStudio Server. The rocker/rstudio image ships the + # server pre-installed. We disable authentication because + # the Coder proxy handles access control. + if command -v rserver > /dev/null 2>&1; then + sudo rserver \ + --server-daemonize=0 \ + --auth-none=1 \ + --www-port=8787 \ + --server-user=rstudio > /tmp/rserver.log 2>&1 & + elif [ -x /usr/lib/rstudio-server/bin/rserver ]; then + sudo /usr/lib/rstudio-server/bin/rserver \ + --server-daemonize=0 \ + --auth-none=1 \ + --www-port=8787 \ + --server-user=rstudio > /tmp/rserver.log 2>&1 & + fi + EOT + + # These environment variables allow you to make Git commits + # right away after creating a workspace. They take precedence + # over configuration in ~/.gitconfig. Remove this block if + # you prefer to configure Git manually or via dotfiles. + env = { + GIT_AUTHOR_NAME = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name) + GIT_AUTHOR_EMAIL = "${data.coder_workspace_owner.me.email}" + GIT_COMMITTER_NAME = coalesce(data.coder_workspace_owner.me.full_name, data.coder_workspace_owner.me.name) + GIT_COMMITTER_EMAIL = "${data.coder_workspace_owner.me.email}" + } + + metadata { + display_name = "CPU Usage" + key = "0_cpu_usage" + script = "coder stat cpu" + interval = 10 + timeout = 1 + } + + metadata { + display_name = "RAM Usage" + key = "1_ram_usage" + script = "coder stat mem" + interval = 10 + timeout = 1 + } + + metadata { + display_name = "Home Disk" + key = "3_home_disk" + script = "coder stat disk --path $${HOME}" + interval = 60 + timeout = 1 + } + + metadata { + display_name = "CPU Usage (Host)" + key = "4_cpu_usage_host" + script = "coder stat cpu --host" + interval = 10 + timeout = 1 + } + + metadata { + display_name = "Memory Usage (Host)" + key = "5_mem_usage_host" + script = "coder stat mem --host" + interval = 10 + timeout = 1 + } + + metadata { + display_name = "Load Average (Host)" + key = "6_load_host" + # Get load average scaled by number of cores. + script = <