Automating Developer Environments with Dev Containers

Automating Developer Environments with Dev Containers

Introduction

Development Containers (or Dev Containers for short) have been around for a few years now (since ~2019) and have reached a level of maturity where I’m now comfortable recommending their adoption. I’ve found that Dev Containers are a fantastic tool to help teams build a consistent and productive Developer Experience.

In this post I’ll cover what Dev Containers are, why you should use them and how to get started. While Dev Containers is an open specification that has growing cross-IDE support this post will focus primarily on using Dev Containers with Visual Studio Code (VS Code) as the IDE.

What are Dev Containers?

As hinted by the name Dev Containers builds upon containers (e.g. Docker) to automate your developer environment. Dev Containers allow you to define a pre-configured, containerized developer environment that integrates with your IDE (e.g. VS Code). The benefits of this include:

Easier onboarding of new team members

Setting up the development environment of some projects can be a nightmare, requiring following extensive documentation (if available) to manually install and configure a complex suite of tools. With Dev Containers it can be as simple as:

  • Installing Docker, VS Code, and the VS Code Dev Containers extension on the host system (Windows, Mac, or Linux)
  • Cloning the project, opening with VS Code, and clicking on the open with Dev Container prompt:
  • This will build a Dev Container based on the configuration included in the project and once complete you’ll have a working developer environment ready to use.

Consistent IDE configuration, tooling and runtime versions

No more “it works on my machine!” Dev Containers provide a reproducible developer environment that can be versioned (i.e. with Git) and shared across a team. When a Dev Container configuration change is made team members will be prompted to rebuild the Dev Container:

Project environments are isolated from each other

Trying to switch between multiple projects when tooling is installed directly on the host system can be painful when version or configuration conflicts arise. With Dev Containers each project runs in its own lightweight, isolated environment making it straightforward to have multiple projects on the go at once.

How to configure a Dev Container

A Dev Container can be configured using a .devcontainer/devcontainer.json file in the root of your project. Here’s a simple example showing some useful features:

// .devcontainer/devcontainer.json
{
  "name": "example-devcontainer",
  "image": "mcr.microsoft.com/devcontainers/javascript-node:22",
  "features": {
    "ghcr.io/devcontainers-contrib/features/pre-commit:2": {}
  },
  "postStartCommand": "pre-commit install",
  "customizations": {
    "vscode": {
      "extensions": [
        "esbenp.prettier-vscode"
      ],
      "settings": {
        "editor.defaultFormatter": "esbenp.prettier-vscode",
        "editor.formatOnSave": true
      }
    }
  }
}

This defines an example Dev Container with the following properties:

  • The Dev Container is built using a Node.js version 22 container image: mcr.microsoft.com/devcontainers/javascript-node:22
  • On top of the base image this example is using “features” to install pre-commit. Features provide a convenient way to install many common developer tools: https://containers.dev/features
  • A “postStartCommand” is used to run pre-commit install when the Dev Container starts to automatically install the git hook scripts pre-commit relies on to work.
  • The “customizations” section provides a space for third-party product configuration properties. In this example we configure VS Code to automatically install the esbenp.prettier-vscode extension into the Dev Container and to use it to auto format on save as the default formatter.
  • The VS Code Dev Containers plugin includes a wizard which can guide you through creating a base Dev Container configuration for most popular programming languages. Example templates for various stacks are also available here: https://containers.dev/templates

Dev Container usage with VS Code

This diagram provides a view of how Dev Containers work when used with the VS Code IDE:

VS Code will mount your source code into the Dev Container and seamlessly run most aspects of your project using the Dev Container.

  • When you open a terminal in VS Code it will attach to your Dev Container allowing you to run software provided by your Dev Container setup (e.g. node.js, python, etc.)
  • VS Code extensions are installed into the Dev Container. This means when you run a test or use the debugger through the VS Code user interface it will use the tooling configured in your Dev Container.
  • We you run a web server inside the Dev Container the port will be accessible on the host system via localhost. If you are building a website for example this allows the host system’s web browser to easily connect to the website running inside the Dev Container.

Not for all projects

Dev Containers work well for developing web and enterprise software targeting deployment to Linux-based server environments. This accounts for a high proportion of modern projects and when combined with VS Code’s wide range of extensions most programming language ecosystems are reasonably well supported. For applications targeting deployment to other environments, e.g. native desktop and mobile app projects, I’d advise using alternative approaches for now.

Other Tips

Other Resources

No Comments

Leave a Reply

Discover more from Shine Solutions Group

Subscribe now to keep reading and get access to the full archive.

Continue reading