March 18, 2025
March 18, 2025 Marco

Dev Containers: Develop inside a container

Well, it works on my machine ¯\_(ツ)_/¯

As engineers and developers, we constantly juggle different tools, dependencies, and environments, especially when building applications with fast-paced AI services. One project requires Python 3.10 with a specific set of modules, another demands Node.js 18 with a global package installed, and yet another needs a completely different toolchain. Switching between these setups often leads to broken dependencies, version mismatches, or hours spent troubleshooting environment issues.

Dev Containers in VS Code address these issues by providing a containerized development environment that can be versioned and shared within your project repository.

In this article, we’ll explore what Dev Containers are, how they work, their advantages, and how you can configure them to match your project needs.

What Are Dev Containers?

Dev Containers, originally introduced by Microsoft, are a feature in Visual Studio Code that allows you to create reproducible, containerized development environments using Docker. You basically define your environment in a JSON definition, from which VSCode builds a container and opens the project in it. The Dev Container Specification is now an open standard, maintained by the Dev Container Community under the Open Container Initiative (OCI), with contributions from Microsoft, GitHub, and other organizations.

Instead of dealing with dependency issues or installing tools manually, you define everything in a devcontainer.json file. Your code and settings are either mounted or copied into the container, and all VS Code features – like extensions – run inside it. This makes switching between projects easy and ensures everything works the same, no matter where you’re coding. This also allows you to store your devcontainer.json definition file in a repository alongside your project and eliminates the hassle of getting all the dependencies right, e.g. when sharing tutorials or entire projects.

Advantages of Using DevContainers

There are many advantages, some of them are:

  1. Dev environment in Git – You can store devcontainer.json configuration files inside your repository, making your dev environment portable.
  2. Support for multiple languages & frameworks – Use predefined Docker images with the required dependencies.
  3. Customizable – Extend the environment with additional configurations.
  4. Works with GitHub Codespaces – Dev Containers form the basis of GitHub Codespaces, allowing cloud-based development.
  5. Supports CI/CD pipelines – Use the same containerized environment in CI/CD workflows.
  6. Reduces onboarding time – Eliminates the need to install dependencies manually.
  7. No more manual setup – Define all tools, libraries, and runtimes in a devcontainer.json file, and let VS Code handle the rest.
  8. Encourages best practices – Enforces infrastructure-as-code principles for development setups.
  9. Run anywhere – Since Dev Containers are based on Docker, they can run in the cloud, on a local machine, or even in GitHub Codespaces.
  10. Safe experimentation – Test new dependencies or tools without breaking your local setup. Just rebuild the container if needed.

Dev Container Definition

The devcontainer.json file contains the configurations and settings for your Dev Container in a JSON schema. This includes pre-packaged tools, VS Code extensions and settings, forwarded ports, and more. In a basic setup, you’ll need:

PropertyTypeDescriptionExample
namestringA name for the dev container displayed in the UI."name": "devcontainers-demo",
imagestringThe name of an image in a container registry (DockerHub, GitHub Container Registry, Azure Container Registry). "image": "mcr.microsoft.com/devcontainers/base:ubuntu",
featuresobjectFeatures are reusable, prepackaged, modular components that install tools, languages, or configurations in a Dev Container, e.g. Git.features": { "ghcr.io/devcontainers/features/git": {} }
customizationsobjectProduct specific properties, e.g. VS Code extension settings.
"customizations": {
"vscode": {
"extensions": [
"ms-vscode.azurecli",
"ms-azuretools.vscode-bicep"
],
"settings": {
"terminal.integrated.defaultProfile.linux": "bash",
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
}
}
},
postCreateCommandstring,
array,
object
Run commands inside the container after the creation.

This command is the last of three that finalizes container setup when a dev container is created. It happens after updateContentCommand and once the dev container has been assigned to a user for the first time.
"postCreateCommand": "if [ -f \"requirements.txt\" ]; then pip install -r requirements.txt; fi && echo 'Post-creation setup complete ✅'",

You can find all available properties in the official reference documentation: Dev Container metadata reference

How to Create Dev Containers

Creating a Dev Container is fairly simple. Let’s go through it step by step.

Step 1: Install Required Tools

  • Install VS Code
  • Install the Dev Containers extension (ms-vscode-remote.remote-containers)
  • Install Docker

Step 2: Prepare the Project Folder

Create a new project folder and open it in VSCode.

mkdir sample-project
cd sample-project

# Open the current folder in VS Code using the command below or right-click the folder in File Explorer and select "Open with Code"
code .

Now, add the devcontainer.json file. By default, it’s placed inside a .devcontainer folder, but it can also be stored elsewhere. VS Code will automatically detect it anywhere within the project folder. Create the following file structure:

mkdir .devcontainer
New-Item -Path .devcontainer\devcontainer.json -ItemType File

Your project folder now has the following structure:

/sample-project
│── .devcontainer/  
│   ├── devcontainer.json

Step 3: Add Dev Container Configuration

Here’s a definition I commonly use for my projects. It will:

  1. use the base:ubuntu image from the Microsoft container registry
  2. install various features so that I don’t have to install them manually, e.g. PowerShell including modules
  3. install VS Code extensions
  4. configure VS Code settings for the container environment (and very important: load Clippy in VS Code Pets extension 😜)
  5. install Python modules from the requirements.txt file, if one exists
  6. set my user name to batman
{
  "name": "devcontainers-demo",
  "image": "mcr.microsoft.com/devcontainers/base:ubuntu",
  "features": {
    "ghcr.io/devcontainers/features/azure-cli:1": {
      "installBicep": true
    },
    "ghcr.io/devcontainers/features/powershell:1": {
      "modules": "Az.Accounts, Az.Resources"
    },
    "ghcr.io/devcontainers/features/common-utils:2": {},
    "ghcr.io/devcontainers/features/git:1": {},
    "ghcr.io/devcontainers/features/python:1": {
      "version": "latest"
    }
  },
  "customizations": {
    "vscode": {
      "extensions": [
        "formulahendry.auto-rename-tag",
        "ms-vscode.azurecli",
        "ms-azuretools.vscode-bicep",
        "ms-python.black-formatter",
        "sleistner.vscode-fileutils",
        "esbenp.prettier-vscode",
        "vsls-contrib.gitdoc",
        "GitHub.copilot",
        "GitHub.copilot-chat",
        "ms-toolsai.jupyter",
        "ms-python.python",
        "ms-python.vscode-pylance",
        "ms-python.debugpy",
        "oderwat.indent-rainbow",
        "wayou.vscode-todo-highlight",
        "vscode-icons-team.vscode-icons",
        "tonybaloney.vscode-pets"
      ],
      "settings": {
        "terminal.integrated.defaultProfile.linux": "bash",
        "editor.formatOnSave": true,
        "editor.defaultFormatter": "esbenp.prettier-vscode",
        "vscode-pets.petSize": "medium",
        "vscode-pets.petType": "clippy",
        "workbench.iconTheme": "vscode-icons",
        "todohighlight.keywords": [
          {
            "text": "FEATURE:",
            "color": "white",
            "backgroundColor": "#68ba7f"
          }
        ]
      }
    }
  },
  "postCreateCommand": "if [ -f \"requirements.txt\" ]; then pip install -r requirements.txt; fi && echo 'Post-creation setup complete ✅'",
  "remoteUser": "batman",
  "forwardPorts": [],
  "mounts": []
}

Step 4: Build and Start the Dev Container

There are two common ways to start a Dev Container

  • Open the Command Palette (Ctrl + Shift + P) and run Dev Containers: Reopen in Container
  •  Click on the blue Open a Remote Window icon in the bottom left corner and run Reopen in Container

VS Code will now build the container and open the project inside it, as indicated in the bottom left corner. You can also view the newly created container in Docker Desktop.

Dockerfile

You can also create a Dev Container from a Dockerfile. This makes sense when you need a customized development environment with specific dependencies, configurations, or tools that aren’t available in a base image.

For a more detailed explanation of using Dev Containers with a Dockerfile, check out this guide: Using Images, Dockerfiles, and Docker Compose

Manage and Maintain

Keep in mind that the container should not be treated as persistent. You should always be able to create a new container, so you should update any changes to the devcontainer.json file. After editing the devcontainer.json file, the container must be rebuilt. You might get prompted automatically after saving your devcontainer.json file; otherwise, again, click on the blue Open a Remote Window icon in the bottom left corner and run Rebuild Container.

Cheat Sheet

I’ve started a GitHub project for cheat sheets and just added the first one on Dev Containers. It includes helpful quick links, examples, and references to the individual configurations.

Take a look and feel free to star the repo to stay up to date: Dev Containers Cheat Sheet

Dev Containers vs. GitHub Codespaces

A Dev Container is a locally hosted development environment that runs inside a Docker container using VS Code. GitHub Codespaces, on the other hand, is a cloud-based development environment that runs on GitHub’s infrastructure. It also uses Dev Containers under the hood, meaning the same devcontainer.json file that configures a local Dev Container can be used to set up a Codespace in GitHub. This allows seamless switching between local and cloud development while maintaining the same setup.

Conclusion

Dev Containers in VS Code are a powerful tool for ensuring a consistent, reproducible, and customizable development environment. For me, it really helps with easy environment setup depending on the project and tools I need, bundled with version control inside a project. Give it a try!

Resources

, ,
Marco Gerber

Marco

Senior Cloud Engineer, keen on Azure and cloud technologies.

Leave a Reply

Your email address will not be published. Required fields are marked *