Data Science

Finally Got Positron IDE Working Smoothly with Dev Containers

Struggling with Positron IDE in Dev Containers? This guide walks you through the exact `devcontainer.json` and Dockerfile setup for a smooth, reproducible workflow.

A

Alex Garcia

Data scientist and developer passionate about creating reproducible and efficient analytics workflows.

7 min read13 views

There are moments in a developer’s life that feel like Christmas morning. For me, one of those was the announcement of Positron, RStudio's polished IDE experience integrated directly into VS Code. The promise was intoxicating: the best-in-class R and Quarto tools I love, living inside the hyper-flexible, polyglot editor I already use for everything else. My mind immediately jumped to the holy grail of modern development: Dev Containers.

I envisioned a world where I could clone a repo, click “Reopen in Container,” and have a perfectly configured R, Python, and Quarto environment spin up, complete with Positron, ready for reproducible analysis. No more “it works on my machine.” No more conflicting package versions. Just pure, containerized bliss.

And then I tried it. And it… didn’t quite work. The Positron pane was blank. The R session couldn't find its kernel. The dream felt a little further away. After a few evenings of tinkering, tweaking, and a lot of container rebuilding, I’m thrilled to say I’ve cracked it. The setup is now as smooth as butter, and it’s every bit as good as I had hoped. If you've been on the same journey, let me save you some time.

The Dream: A Unified, Reproducible Workflow

Before we dive into the nuts and bolts, let’s quickly recap why this setup is worth the effort. VS Code Dev Containers allow you to define your entire development environment—OS, runtimes, extensions, settings, and dependencies—as code. This brings several massive advantages to data science:

  • Perfect Reproducibility: Anyone on your team (or your future self) can recreate the exact environment with a single command. This is the ultimate cure for dependency hell.
  • Clean Separation: Each project lives in its own isolated container. No more worrying that installing a package for Project A will break Project B.
  • Simplified Onboarding: New team members can be productive in minutes, not days. Just clone the repo and open it in a container. The entire toolchain is there.

Bringing Positron into this mix elevates it further. You get RStudio's thoughtfully designed data variable explorer, R Markdown/Quarto visual editor, and plot pane, all within the same VS Code window where you’re writing Python scripts, managing dbt models, or editing your infrastructure-as-code. It's the unified environment data scientists have been waiting for.

The Stumble: First Encounters and Frustrations

My initial attempt was naive. I took a standard Python dev container, added the Positron extension to my `devcontainer.json`, and hoped for the best. The results were… underwhelming. I ran into a few key problems:

  1. The Blank Pane of Despair: The Positron side pane would appear, but it was just an empty void. No R session, no variable explorer, nothing.
  2. Kernel Catastrophe: When I tried to run an R chunk in a Quarto document, it would complain that it couldn't find the `R` executable, even though I had installed it in my Dockerfile.
  3. Port Forwarding Puzzles: Even if I could get a Shiny app or Quarto preview to launch, VS Code wouldn't automatically forward the port, forcing me to manually configure it every time.

These issues all stemmed from the container environment not being configured in a way that the Positron extension expected. It needs specific paths, permissions, and settings to hook into the R runtime correctly.

The Breakthrough: A Step-by-Step Guide to a Smooth Setup

Advertisement

Alright, let's get to the good part. Here is the configuration that finally got everything working together seamlessly. We'll be creating two key files in a .devcontainer directory in your project root: devcontainer.json and Dockerfile.

Prerequisites: Getting Your Ducks in a Row

Make sure you have the following installed on your host machine:

Crafting the devcontainer.json for Positron

This file is the control center for your environment. It tells VS Code how to build and configure the container, which extensions to install, and what commands to run.

{
  "name": "R & Python Data Science",
  "build": {
    "dockerfile": "Dockerfile"
  },
  "customizations": {
    "vscode": {
      "extensions": [
        "rstudio.positron",
        "quarto.quarto",
        "ms-python.python",
        "ms-toolsai.jupyter"
      ],
      "settings": {
        "r.rpath.linux": "/usr/bin/R",
        "r.bracketedPaste": true
      }
    }
  },
  "forwardPorts": [8787, 3838],
  "postCreateCommand": "Rscript -e 'renv::restore()' && pip install -r requirements.txt",
  "remoteUser": "vscode"
}

Let's break down the important parts:

  • build.dockerfile: Points to our custom Dockerfile, which we'll create next.
  • customizations.vscode.extensions: This is critical. We're explicitly telling the container to install Positron, Quarto, and the official Python extension. This ensures they're available inside the container, not just on your local machine.
  • customizations.vscode.settings: The r.rpath.linux setting explicitly tells the R-related extensions where to find the R executable inside the container. This solved my "kernel not found" issue.
  • forwardPorts: We're proactively telling VS Code to forward ports commonly used by RStudio Server components (8787) and Shiny (3838). This makes previews and apps just work.
  • postCreateCommand: A huge time-saver. After the container is built for the first time, this command runs automatically. Here, I'm using it to restore my R packages from an `renv.lock` file and install my Python packages from `requirements.txt`.
  • remoteUser: We run as the non-root `vscode` user, which is a security best practice and avoids many file permission headaches.

The Dockerfile: Building the Right Environment

The `Dockerfile` defines the actual image. We'll start from a base image and add R, Python, and the necessary system dependencies that R packages often need for compilation.

# Start from a base dev container image that includes Python and Node
FROM mcr.microsoft.com/devcontainers/base:ubuntu-22.04

# Avoid prompts from apt
ENV DEBIAN_FRONTEND=noninteractive

# Install system dependencies needed for R and common R packages
RUN apt-get update && apt-get install -y --no-install-recommends \
    software-properties-common \
    dirmngr \
    libssl-dev \
    libcurl4-openssl-dev \
    libxml2-dev \
    libcairo2-dev \
    libxt-dev \
    libpng-dev \
    libjpeg-dev \
    && apt-get clean && rm -rf /var/lib/apt/lists/*

# Add R repository and install R
RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E298A3A825C0D65DFD57CBB651716619E084DAB9
RUN add-apt-repository 'deb https://cloud.r-project.org/bin/linux/ubuntu jammy-cran40/'
RUN apt-get update && apt-get install -y --no-install-recommends r-base r-base-dev

# Install Quarto CLI
RUN \
    ( \
        LATEST_QUARTO=$(wget -q -O - https://api.github.com/repos/quarto-dev/quarto-cli/releases/latest | grep -o -E 'https://.*/quarto-.*-linux-amd64.deb' | head -n 1) && \
        wget -O quarto.deb "${LATEST_QUARTO}" && \
        dpkg -i quarto.deb && \
        rm quarto.deb \
    )

# Switch back to the non-root user
USER vscode

# Pre-install renv for package management
RUN R -e "install.packages('renv')"

This Dockerfile does a few key things:

  1. It starts from a standard Microsoft base image.
  2. It installs a list of common system libraries (libssl-dev, libxml2-dev, etc.). This step is crucial and often overlooked. Many R packages like tidyverse, curl, and xml2 need these to compile from source.
  3. It adds the official R repository and installs the latest version of R.
  4. It dynamically finds and installs the latest version of the Quarto CLI.
  5. Finally, it switches to the `vscode` user and pre-installs the `renv` package, getting it ready for our `postCreateCommand`.

The Launch Sequence

With those two files inside your .devcontainer folder, the hard part is over. Now, you just:

  1. Open your project folder in VS Code.
  2. A small pop-up should appear asking if you want to “Reopen in Container.” Click it. (If not, open the command palette with Ctrl+Shift+P and select “Dev Containers: Reopen in Container”).
  3. Grab a coffee. The first build will take a few minutes as it downloads the base image and runs all the steps in your Dockerfile. Subsequent launches will be much faster.

When it finishes, you'll have a VS Code window running inside your custom environment. Open a .qmd or .R file, and you should see the Positron pane light up, ready to go. You can now execute R code, see your plots, and manage your variables, all in a self-contained, reproducible environment.

Conclusion: The Payoff is Worth It

Yes, there are a few hoops to jump through to get this working. It's not quite a one-click install... yet. But the initial investment of setting up these configuration files pays dividends on every single project.

The combination of Positron's polished R integration and the power of Dev Containers creates an environment that is robust, reproducible, and a genuine pleasure to work in. You get the best of both worlds: RStudio's data science ergonomics and VS Code's world-class editor and extension ecosystem. For any data scientist who juggles R and Python, this is a setup that will fundamentally improve your workflow.

Now that the foundation is laid, the possibilities are endless. You can add project-specific dependencies, define debug configurations, and share this perfect environment with your entire team. Go give it a try—your future self will thank you.

Tags

You May Also Like