CCBR Code Club
Oct 07, 2026
| language | environments | |
|---|---|---|
| pip | python | ❌ |
| uv, venv, pyenv | python | ✅ |
install.packages, pak |
R | ❌ |
| renv | R | ✅ |
| conda, mamba | polyglot | ✅ |
| pixi | polyglot | ✅ |
Install dependency versions on your local machine.
There can be slight differences in compiled versions of software depending on the hardware and operating system.
Ship with exact versions of dependencies already compiled and installed for a specific OS.
Extremely useful for pipelines; each step gets its own container. Users don’t have to worry about installing dependencies.
Architecture of Dev Containers. Source: https://code.visualstudio.com/docs/devcontainers/containers
| Biowulf HPC | GFE macOS | ||
|---|---|---|---|
| ❌ | ❌ | Industry standard, but incompatible with HPC due to root privileges. CBIIT won’t allow Docker on macOS due to security concerns. | |
| ✅ | ❌ | Great for HPC, doesn’t support macOS. CLI not exactly identical to docker, but generally compatible. | |
| ❌ | ✅ | Could be installed on Biowulf in the future. CLI is a drop-in replacement for docker. Rootless by default. |
Download Podman Desktop from podman.io
Install and open Podman Desktop
Create new podman machine
Increase the default resource allocation. Make sure it is rootless!
Machine is now running
Optional: auto-start the machine when podman starts
Optional: start podman when you login. Consider toggling on if you use podman daily, or toggle it off if you use it sparingly.
Install the Dev Containers extension
podman-composewhich podman ➡️ /opt/podman/bin/podman)Change settings to use podman instead of docker
File > Open or
Dev Containers: Reopen in ContainerTip
Disconnect from the VPN when pulling a base container for the first time – it may interfere with the download.
It will take some time to build the container the first time. After that it will cache the image and perform much faster.
Container image built from a local file:
Benefit of building from a local Dockerfile: you can edit the Dockerfile and immediately use it to rebuild the Dev Container.
Using a pre-built image means if you edit the Dockerfile, you would first have to build and push a new image tag to a container registry, then rebuild the Dev Container from the new tag.
The extension detects when the config file changes and will prompt you to rebuild the container.
You can also trigger a rebuild via the command palette.
This session had the multiOmicDataSet repo attached the workspace.
Copilot was unable to write to a file in another repo.
If it went rogue and tried to anyway, it would be incapable of doing so.
Option 1: One Dev Container per repository, open a separate VS Code window for each repo you’re working on.
Tip
This works best when the projects are mostly unrelated and not interdependent.
Option 2: Create a workspace with repos in subdirectories. Only need to open one VS Code window for the workspace.
VS Code workspace
~/projects/NIDAP
├── .devcontainer/
│ ├── devcontainer-lock.json
│ └── devcontainer.json
├── Code-Ocean.code-workspace
├── Code-Ocean-Capsule-Template/
├── demo-syncweaver-host-capsule/
├── demo-syncweaver-source-monorepo/
├── MOSuite-batch-correct-counts/
├── MOSuite-clean/
├── MOSuite-create/
├── MOSuite-diff-counts/
├── MOSuite-filter-counts/
├── MOSuite-filter-diff/
├── MOSuite-normalize-counts/
├── OMIX/
└── ...Tip
This option works best for projects with multiple related and interconnected repositories. If you often need to edit code across multiple repos for a given task, set up a workspace with all of those repos.
Tip
These 2 options are not mutually-exclusive. You can mix-and-match as you see fit!
Look for samples and template Dev Containers from established projects for inspiration.
Open the command palette (F1F1) and search for “sample”.
Development container “Features” are self-contained, shareable units of installation code and Dev Container configuration. The name comes from the idea that referencing one of them allows you to quickly and easily add more tooling, runtime, or library “Features” into your development container for use by you or your collaborators.
Registry of Features: https://containers.dev/features
devcontainer.json
{
"name": "Data Science (Python and R)",
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
// Features to add to the Dev Container. More info: https://containers.dev/features.
"features": {
"ghcr.io/devcontainers/features/python:1": {
"version": "latest"
},
"ghcr.io/rocker-org/devcontainer-features/r-apt:latest": {
"vscodeRSupport": "full",
"installDevTools": true,
"installRadian": true,
"installRMarkdown": true,
"installVscDebugger": true
},
"ghcr.io/rocker-org/devcontainer-features/apt-packages:1": {
"packages": "r-cran-data.table,r-cran-tidyverse",
"upgradePackages": true
}
},
"overrideFeatureInstallOrder": [
"ghcr.io/rocker-org/devcontainer-features/r-apt"
],
// Use 'postCreateCommand' to run commands after the container is created.
"postCreateCommand": "pip install ipykernel ipywidgets && if [ -f requirements.txt* ]; then pip install -r requirements.txt; else pip install pandas numpy matplotlib seaborn scikit-learn; fi",
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
// Configure tool-specific properties.
"customizations": {
// Configure properties specific to VS Code.
"vscode": {
// Set *default* container specific settings.json values on container create.
"settings": {
"[python]": {
"defaultInterpreterPath": "/opt/conda/bin/python",
"editor.defaultFormatter": "ms-python.black-formatter",
"editor.formatOnType": true,
"editor.formatOnSave": true
},
"[jupyter]": {
"themeMatplotlibPlots": true,
"widgetScriptSources": [
"unpkg.com",
"jsdelivr.com"
]
},
"[r]": {
"rterm.linux": "/usr/local/bin/radian",
"r.bracketedPaste": true
}
},
// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"ms-toolsai.jupyter",
"ms-python.python",
"reditorsupport.r"
]
}
},
// Set `remoteUser` to `root` to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"remoteUser": "vscode"
}When you start using Features, a devcontainers-lock.json will be created alongside the config file to pin the exact Feature versions.
datascience-py-r on previous slide).Anything a user would need to run the code. In dependencies of pyproject.toml file, Imports of DESCRIPTION, or imported/loaded by an analysis script.
MOSuite requires DESeq2; ccbr_tools requires biopython.
Anything unrelated to the execution of the code but assists in development and may not be universally used by all developers/contributors.
VS Code extensions, GitHub CLI, Copilot CLI, Codex CLI.
In project.optional-dependencies of pyproject.toml or Suggests: of DESCRIPTION file. Anything that assists developers in chores: testing, linting, etc.
devtools, testthat, air for R code; pytest & ruff for Python code.
Most git commands will work, but GitHub credentials must be shared with the container in order to do git fetch/push/pull.
Important
Add the GitHub CLI Feature to your Dev Container config:
Then authenticate:
Terminal
$ gh auth login
? Where do you use GitHub? GitHub.com
? What is your preferred protocol for Git operations on this host? SSH
? Generate a new SSH key to add to your GitHub account? No
? How would you like to authenticate GitHub CLI? Login with a web browser
! Failed to copy one-time code to clipboard
No clipboard utilities available. Please install xsel, xclip, wl-clipboard or Termux:API add-on for termux-clipboard-get/set.
! First copy your one-time code: XXXX-XXXX
Press Enter to open https://github.com/login/device in your browser...
✓ Authentication complete.
- gh config set -h github.com git_protocol ssh
✓ Configured git protocol
! Authentication credentials saved in plain text
✓ Logged in as kelly-sovacoolNow you can use gh CLI commands from inside the Dev Container.
When opening the Dev Container fails instantly, make sure you started the podman machine.
When opening the Dev Container fails instantly, make sure you started the podman machine.
If processes in the Dev Container fail due to insufficient resources (memory, disk space), increase the resources for the default podman machine and restart it.
When the container fails to be built, copy the log from the terminal.
Diagnosis from Copilot:
Podman’s –cache-from only accepts a repository name, while Docker also accepts a tagged image
So far I’ve shown you how to get started using Dev Containers in VS Code on macOS.
Positron supports Dev Containers!
…but I haven’t gotten it to work 😿
Instructions in positron’s documentation to enable development containers: https://positron.posit.co/dev-containers.html
But these could change in the future!