Skip to main content

Saving Your Sanity with VSCode Dev Containers

·4 mins

Oh Yeah! #

Randy Savage

This is a photo of me getting ready to tell you about the number one piece of technology everyone should be using but don’t seem to be: VSCode Dev Containers.

Notice: Please read over the VSCode Dev Containers Documentation for actual usage instructions. This post is meant to show it can be extremely useful for DevOps situations, add some pointers, and won’t cover usage beyond summarizing.

Before I can convey how useful dev containers have been in my line of work (DevOps), let me describe the problems I had before I started using them.

A Repetitive Waste of Time #

On any given day, an engineer in my team would work on a few solutions across a few customers. It lead to the following workflow:

  • Engineer opens the solution, creates a git feature branch, begins dev work,
  • Examines the README to determine if the last engineer left any specific instructions for deployment,
  • Discovers that there are problems because the solution was created by an engineer with an x86_86 Windows system, where the current engineer needs to use it on an ARM64 Mac; and/or,
  • Discovers that they are going to have to go through a lot of tool adjustments to meet the version requirements laid down by the solution because they have different/incompatible versions currently installed.

It was common to spend several minutes just getting to a point where development can truly begin. If a junior engineer was starting a task, it usually involved them reaching out to a senior engineer for help.

To complicate matters more, many of these solutions ran within Linux based CI/CD pipelines. It was very hard to do local development in a Mac/Windows environment and feel confident you had identical behavior within the pipeline.

What is a Dev Container? #

In the case of VSCode Dev Containers (there are other dev container offerings):

  • A .devcontainer directory is added to the root of the solution repository. This directory contains a Dockerfile describing how the environment should be built, and a devcontainer.json file defining VSCode settings,
  • When the repo is opened in VSCode, the Dev Containers extension is used to launch the container defined in the .devcontainer directory.

After VSCode builds and launches the container, it then installs a VSCode server into it. VSCode’s UI then connects to it and performs all operations within the container, while keeping the UI in your native environment. To the end user VSCode looks mostly the same, with the exception of it appearing to be operating in a Linux system, because it is.

This gives every user a single consistent environment. Even better, this Dockerfile can also be used in your CI/CD pipeline to ensure it is operating in the same environment as the engineers.

A Better Way #

By implementing VSCode Dev Containers along with some dev container design standardization, we were able to completely eliminate our problems.

In addition to the VSCode Dev Container documentation, I would recommend doing the following:

  • A .devcontainer is set up for each solution, with the following requirements during setup time:
    • The base container used has x86_64 and ARM64 versions in the container registry. This prevents ARM64 Mac users from running things in slow/buggy x86_64 emulation,
    • Any supporting tools used (Terraform, linters, etc) must support both x86_64 and ARM64,
    • The Dockerfile customizations must include some basic logic to detect architecture and install the proper versions of the tools. Do not include customizations in the Dockerfile that will not work in all environments.
    • Keep in mind some tools are best for the job (i.e., Poetry for Python packages). These tools may work even better within a dev container, as they will have less package types to worry about. Don’t feel compelled to have to handle this in the Dockerfile, feel free to use a Poetry config in the repo in addition to the dev container config.

By following the above guidelines, anyone on the team can open a repo, launch its dev container, and begin work without fuss.

Further Improvements #

Using the time saved, senior level engineers on the team are able to spend more time on feature rich dev container environment templates. Rather than having the basics for deployment, we now have common dev container templates we can drop in to projects complete with advanced linters, VSCode extensions, VSCode customized settings, and so on.

Junior engineers are able to begin work without issue, and have all the IDE niceties the senior engineers added into the dev container. They are able to learn why these tools are nice to have before they even know how to install the tools themselves.

We are also able to provide these improvements to the customer along with the solutions. The documentation we provide along with the solution is able to be reproduced exactly the same way as we experienced during development.

Give it a shot, you’ll be glad you did.