Using Docker as a Dev Environment with VS Code: Part 1

Docker has become an established, convenient tool for developers who manage complex local dev environments. Testing and running multi-service web applications become easier when each can be containerized and mimic its production environments.

Why not take advantage of the same benefits for our actual development work? In this two-part series, I’ll go over how to use Docker not just for build targets but for actively writing code on your projects. If you’ve torn your hair out in frustration after a “brew upgrade” broke your build, this post about developing in Docker is for you.

Remote-Containers in VS Code

The VS Code Remote Containers extension makes it easy to use a Docker container as a local code development environment. You don’t even need to be using Docker on your project yet to get started.

At its simplest, the extension gives you the ability to attach to a running container. You can also edit your project code with VS Code directly from within that environment.

“But Dylan,” you say, “I can already edit my code on my host machine and still have those changes reflected in the Docker container. Why would I want to develop inside the container?”

Managing the Package Managers

For anyone who’s ever used homebrew, pyenv, rvm, or any other headache-inducing environment and version manager, the benefit of containerized development should be obvious. Managing the tools we use to write code and all their myriad versions and dependencies is no easy task.

Constraining your development to a Dockerized environment shifts the burden of tool management to properly maintaining your containers. Additionally, editing all your code in Docker containers means never having to worry if the correct version of Python is installed and in your $PATH.

Creating Your First Development Container

After you install the extension, run “Remote-Containers: Open Folder/Workspace in Container…” from the VS Code command palette. Next, a prompt will ask you to make some choices about which Docker container you want to use. Go ahead and pick a sane default for your project. You can easily change it later!

The first time you run this, it will take a little while for the Docker image to download and build before VS Code attaches the editor. Once your project loads, you’ll notice a new folder in the root named .devcontainer. This is where VS Code stores its devcontainer.json Remote-Containers configuration file, as well as the Dockerfile for the container that you just built.

If you’d prefer, you can get rid of the .devcontainer folder. Just move the config file to the root of your project and rename it .devcontainer.json (with a leading .). Put the Dockerfile anywhere you’d like, and then update the config file’s path:


"build": {
  "dockerfile": "path/to/Dockerfile",
}

That’s it. Now you’re editing code in Docker! By default, your code is bind-mounted from your host machine. That means any changes you make will still be saved even if you close your VS Code window (which will shut down the Docker container). This isn’t always preferable, so I’ll cover more advanced options for that in the next post.

Configuring Your Dev Environment

The next step is to better configure your Dockerfile for your project’s needs. This depends a lot on which image you choose, but you’ll probably use something like apt in Ubuntu to install further tools like npm or yarn.

A lot of the available pre-made Docker base images might have everything you need already. This repository from Microsoft provides a lot of templates to choose from.

You can also further customize the devcontainer.json config file. There are two options you’ll probably want to edit.

The first is “extensions,” which lets you list VS Code extensions you’d like to install inside the container. This allows you to create a custom editing environment for a particular project. It also ensures that anyone else using your repository to develop in a container will have all the correct VS Code extensions installed.

The second is the “postCreateCommand” which allows you to run commands inside the container after you build it. This is great for running shell scripts or things like npm install that don’t belong in the Dockerfile.

A full devcontainer.json might look like this:


// For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.112.0/containers/typescript-node-12
{
  "name": "Atomic Object Example Project Container",
  "service": "app",
  "shutdownAction": "stopContainer",
  // Set *default* container specific settings.json values on container create.
  "settings": {
    "#terminal.integrated.defaultProfile.linux#": "/bin/bash"
  },
  // Add the IDs of extensions you want installed when the container is created.
  "extensions": [
    "dbaeumer.vscode-eslint",
    "esbenp.prettier-vscode",
    "ms-vsliveshare.vsliveshare"
  ],
  "postCreateCommand": "yarn install"
}

The VS Code Remote-Containers documentation goes into more detail about all the ways you can get started developing in a container here.

What’s Next?

This post was just a taste to get you started developing in Docker with VS Code. In my next post, I’ll go into detail about different ways to handle a more complex dev environment.

Conversation
  • Glen says:

    Hello,

    You have a frustrating habit of writing something like “In my next post, I’ll go into detail about …”

    But you don’t come back and add a link to that post. Makes it really hard to follow in sequence.

    Regards

  • Comments are closed.