DevContainers: what, how and why?

Idempotence in Modern Software Development Environments

Eliezer Bernart
Poatek
4 min readOct 25, 2023

--

Before discussing DevContainers, we need to define a very old concept that has become a new trend in modern software development environments: Idempotence. There is nothing better to define classic things as modern LLMs; here is a short one using OpenAI Chat GPT 3.5:

Idempotence is a property in which a specific operation can be applied multiple times, but the result remains the same as if applied once.

Translating that same concept to software development, in simple terms, we want to have the same code, project, or application to behave the same if it is the first time or the tenth time you are running it. Docker containers played a very important role in bringing idempotence to deployment, but container development was still very challenging if one was not fully proficient with Docker environments. That’s when DevContainers came into play.

Poatek Office in Porto Porto Alegre — Brazil

At Poatek, we want to make sure that developers, either interns or seniors, have a very smooth process of joining on-going projects. Adopting DevContainers helped us provide such an environment to our teams and improve our documentation and deployment process!

What is a DevContainer?

DevContainer is a specification for using Docker containers in software development, using the definition from their website (why not):

A Development Container allows you to use a container as a full-featured development environment. It can be used to run an application, to separate tool libraries, or run times needed for working with a codebase and to aid in continuous integration and testing. Dev containers can be run locally or remotely, in a private or public cloud, in various supporting tools and editors.

Different platforms already support DevContainers, such as Microsoft VSCode, Github Codespaces, and IntelliJ IDEA. From this list, VSCode is probably the one that offers the largest amount of capabilities and will be covered in this article.

To follow the steps highlighted here, you must have VSCode and Docker Desktop installed on your computer. If you are on Windows, just as I am, you can install them using winget a very practical CLI (Command Line Interface) built-in on the latest version of Windows.

winget install Docker.DockerDesktop
winget install Microsoft.VisualStudioCode

The next step is to install the VSCode extension DevContainers:

DevContainer extension on Microsoft VS Code

DevContainers are saved in your project or repository folder alongside the other files. They are kept in a folder .devcontainer and stored in the devcontainer.json file. Here is a sample file of what a very simple DevContainer configuration file looks like:

{
"name": "Python 3",
"image": "mcr.microsoft.com/devcontainers/python:1-3.11-bullseye"
}

We are ready to open our project using the specified DevContainer! After our project is reopened into our container, we can see that our Terminal already opens by default in the container machine we set up in our configuration file.

Project inside DevContainer on VS Code

Now we are ready to go!

How to use a DevContainer?

If your application already runs on top of containers for deployment. DevContainer specification supports the usage of Dockerfile and compose.yaml files. This means that no additional build setting is required, you’re almost ready to go out-of-the-box; add the following configuration file, and you are ready to launch. 🚀

{
"name": "My Existing Dockerfile",
"build": {
"context": "..",
"dockerfile": "../Dockerfile"
},

"features": {
"ghcr.io/dhoeric/features/google-cloud-cli:1": {},
"ghcr.io/devcontainers/features/aws-cli": {}
}
}

New features can be added on top of your default Docker image; in this example, GCP and AWS CLI applications will be available for your development only, without any modification to your deployment settings. For a complete list of supported features, look at this list.

Another interesting feature when integrating VSCode and DevContainers is adding a default set of VSCode extensions and settings as part of your devcontainer.json. Everything set up under the sections extensions and settings will be applied by default when your container is built. It is as easy as it gets to share that sweet extension you found with your team.

{
"name": "Python 3",
"image": "mcr.microsoft.com/devcontainers/python:1-3.11-bullseye",
"customizations": {
"vscode": {
"extensions": [
"ms-python.black-formatter",
"ms-python.isort"
],
"settings": {
"terminal.integrated.defaultProfile.linux": "bash"
}
}
}
}

Why use a DevContainer?

There are a lot of benefits to using DevContainers; here is a list of the short-term benefits we have already noticed since our adoption in our environments:

  • 🛬 On-boarding new team members becomes easy;
  • 🚀 Deployment is part of development from the beginning;
  • 📃 Changes in application dependencies are documented;
  • 💻 Baseline development environment for the whole team.

Here are a few more settings that can be included in the capabilities of your devcontainer.json file:

  • Port Forwarding and Attributes (forwardPorts and portsAttributes);
  • Mounting Folders and Units (mount);
  • Container Internals (runArgs, cacheFrom);
  • Container Lifecycle Binds (postAttachCommand, postStartCommand);
  • Custom Environment Variables (remoteEnv).

More information on the documentation page here.

In other words, containers are here stay! They took over as the new standard for application deployment both on-premise and on the cloud, and Docker is supported basically anywhere (if you know a place where it is not, please let us know in the comments). 😜

--

--