Developer's Paradise: Why I Swear by VS Code Devcontainers for Seamless Coding

VS Code’s Devcontainer allow seamless development in Docker containers, ensuring your code runs smoothly across machines while preserving the local development experience. (Image by Sinousxl)

VS Code is probably the most popular integrated development environment (IDE) and many people enjoy the seamless remote development experience using Remote Development via SSH. VS Devcontainer take this a step further to make your life easier: Instead of developing on your host, i.e. on your local machine or on a remote server connected via SSH, you can directly develop inside a Docker container. This means your code can be run without any changes or set up overhead on any other machine. And the best part: you don’t even realize you’re actually using a Devcontainer! Your development experience stays exactly the same - you still feel like working locally.

Why should I use this?

Safe playground for environment development

You want to run some code you found on Github, but the dependencies (e.g. Ubuntu package versions) sound scary to install, since they might interfere with existing, potentially fragile dependencies? When using Devcontainers, this is no problem at all, since every container is a isolated environment which you can freely and quickly configure. Thus, you can iterate the setup steps without ever affecting your local system.

No more setup overhead → Reproducibility for free

Your colleague wants to quickly run or test your code, but his OS is very different from yours? You’re wondering how difficult setting up your code on his machine will be? With Devcontainers the only overhead you have is that you need to wait for the Docker container to build and it will just work out of the box!

How does it affect my development experience?

It doesn’t, that’s the great part! The only thing that changes is that status bar badge in the lower left that will let you know that you’re inside a Devcontainer!

Okay, I lied ;). There are a few (minor?) things to consider:

  • You don’t have access to your local file system, so you need to mount all data (outside your project directory) you want to access into the Devcontainer. But don’t worry, that’s an easy one-liner (see Configuration) and you can organize it however you like!
  • Windows has some issues with high CPU usage (e.g. this or this issue), when you use Devcontainers locally (i.e. you develop inside a container on your machine, and not on a remote via SSH). You might need to restart Docker or your PC from time to time, to mitigate this.
  • Permissions can get screwed up, when you’re root inside the Devcontainer. This can be fixed by not being root inside the container or the good old sudo chown -R USERNAME:USERNAME /PATH/TO/CODE.
  • Devcontainers are not killed when you close the IDE, which is great since you can run code as usual with detached sessions with tools like tmux. However, you should clean up old open Devcontainers from time to time.
  • Pushing to remotes will not work out-of-the-box if you use ssh since the container has it’s own signature. Check this issue for fixes.

How to get started

Installation

You need to (also see the docs)

Configuration

Okay, that’s the installation - now how to configure it?

  • Create a folder .devcontainer in the project root
  • Add a devcontainer.json (see below)
.
├── .devcontainer
  ├── devcontainer.json 
  └── Dockerfile

The devcontainer.json should look something like this (for details the see docs):

{
  "build": {
    "dockerfile": "Dockerfile",  // location of Dockerfile relative to .devcontainer folder
    "args": {
      // OPTIONAL: only when using GPUs
      "runtime": "nvidia"
    }
  },
  "runArgs": [
    // OPTIONAL: only when using GPUs
    "--runtime=nvidia"
  ],
  "customizations": {
    "vscode": {
      "extensions": [  // OPTIONAL: specify which extensions should be installed inside the container
        "ms-python.python",
        "ms-python.vscode-pylance"
      ]
    }
  },
  "mounts": [  // OPTIONAL: if you want to mount a dataset or something similar
    "source=LOCAL/PATH/TO/DATA,target=/DOCKER/PATH/TO/DATA,type=bind,consistency=cached"
  ],
  // OPTIONAL: run commands after creation, e.g. automatic donwload of weights or datasets
  "postCreateCommand": "sh .devcontainer/postcreate.sh",  // relative to project root
}

Usage

Simply press F1 (or CTRL + SHIFT + P) and select Dev Containers: Rebuild and Reopen Container

PS: Yes, the title was generated by ChatGPT ;)