Remote Development with VS Code and Docker

Jul 3, 2019 · 7 min read
Image for post
Image for post
Remote Development with VS Code and Docker

Last month’s release of VS Code (1.35) introduced an exciting set of extensions for remote development. In a nutshell, the three extensions are:

  • SSH - Develop code located within a remote/virtual machine
  • WSL - Develop code in a Linux environment from the comfort of a Windows machine
  • Containers - Develop code with a full-featured development environment in a Docker container

This post will be a deep-dive into Remote Containers. I will introduce the problem domain, explain how remote containers work and demonstrate a use-case.

Problem Domain

Hardships can arise from complex and outdated setup instructions. Of course, keeping documentation up-to-date is a relatively simple process, so these types of problems should (hopefully) not occur very often. However, it’s also possible that you will face complex and unexpected issues that were not mentioned in the “happy-path” instructions provided. These are the types of issues that can lead you down rabbit holes.

A typical example is when a new-joiner tries to set up a project and struggles due to a lack of contextual knowledge and no clear course of action to take. At this point, it is common to search for a quick-fix online and hope someone has encountered the same issue. Yet, this may not yield success and they may potentially add more complexity to an already complex issue. Another option is to ask a colleague for help, as they will have probably followed the same instructions to get set up. However, the problem may not be familiar to them because the setup worked a charm on their machine. This could now consume the time and effort of two engineers, which could have potentially been avoided.

And finally, once you’ve jumped over these hurdles and think you’re ready to write some code, you have to spend time in tweaking your IDE settings and installing your favourite extensions that you just can’t develop without.

What if we could eliminate these pain points with automation? By declaring an environment once, we could create a reliable way of initialising a project and its development space with no manual intervention required. This is where Remote Containers come in handy.

Remote Containers

The extension allows you to declare your environment using a Dockerfile, defined within your project. VS Code uses this Dockerfile to build an image and run a container, which will eventually become your development environment. Along with this, a file called devcontainer.json is required in order to use the extension. This file is used to configure launch settings for the container — we’ll talk more about this a bit later.

Let’s see how this works in practice…



To get started, let’s use create-react-app to initialise a boilerplate project.

npx create-react-app react-vscode-container

Once completed, navigate into the project and create a directory in the root called .devcontainer. This is where the extension will look for our configuration files and recognise that the project supports Remote Containers.

$ cd react-vscode-container$ mkdir .devcontainer

Create two files in this directory: Dockerfile and devcontainer.json.

$ cd .devcontainer$ touch Dockerfile
$ touch devcontainer.json

At this point, we can open our project in VS Code and start to populate these new files.

Your project structure should now look like this:


Firstly, we will edit Dockerfile to be the following:

Dockerfile for Remote Container — React app

Above, we define a container extending the standard Node 10 base image. Then, we configure zsh as our default shell and install ESLint globally.

Secondly, edit devcontainer.json to be the following:

As mentioned earlier, this file configures launch settings for the container. There are a few properties being set here, so lets go through them one-by-one.

name: Friendly display name for the dev container.

Dockerfile: Path to the Dockerfile which will be used to create the dev container.

appPort: Ports to expose from container to host machine. This is useful to be able to access your app from your local machine when it is running in the dev container. In this example, we expose port 3000 as this is where our app runs in the container.

extensions: Extensions to install for VS Code in the dev container. This means you won’t have to install extensions manually, they will be ready to use from initial launch. In this example, we are installing: Bracket Pair Colorizer, React Code Snippets and Sort Lines.

settings: Attributes for the container VS Code settings.json file. In this example, we set the terminal shell to be zsh.

postCreateCommand: Command(s) to run after the container has been created. In this example, we run yarn after creation to install our Node dependencies.

The configurable options provide freedom over your development environment so that you can tailor it to the needs of your project and team. A list of all configurable properties are documented here.

Now, we are ready to launch our development container:

  • CMD/CTRL + Shift + P > Select “Remote-Containers: Reopen Folder in Container”
Image for post
Image for post
VS Code - Reopen folder in container

A new VS Code window will open to run your container. This will take a few minutes on the first launch as an image will be built for the container.

Image for post
Image for post
Installing the development container

Once completed, you will be able to see your project in VS Code. The difference being that this is running inside a development container, not your local machine. To verify this, open another terminal and run the following command which will echo the list of files in the root directory.

$ ls ../../ # bin  boot  dev  etc  home  lib  ....

Notice how zsh is our default shell in the VS Code terminal, as declared earlier. Also, the extensions we listed in devcontainer.json are installed and ready to use.

Image for post
Image for post
Development container launched

You might be wondering how the project folder has magically appeared in the file browser on the left pane. That’s a fair question to ask. Prior to running the container, the extension injects arguments into the Docker launch command. By default, a volume is created for the project directory between the host machine and the container. This ensures that any changes in the container are mirrored on the host machine and vice-versa in order to achieve consistency of states in both environments.

Finally, we can run our app from inside the development container.

$ yarn start

Our app will run within the container on port 3000. Since we specified this port in appPorts, it will be published and we will be able to access it on the host machine via localhost.

Image for post
Image for post
React app running in container and accessed locally

If you make a change to App.js, you will see that hot-reloading still works and the browser will auto-reload once a change is detected.

That’s it! We’ve set up our development environment for this project using Remote Containers.

Github repo for this demo can be found here.


A clear use-case of this feature is simplifying on-boarding processes, so that new-joiners are able to get up and running without facing platform-specific issues. For open-source projects, first-time contributors will require less guidance and face fewer issues related to setup. This will allow contributors to focus on development, rather than development environment. It also means that all users will be developing code in a standardised environment. These are just some of the potential use-cases. The possibilities are endless!

A key benefit of using Remote Containers is that they don’t come with a steep learning curve, meaning it is approachable for those who don’t have experience in dev-ops. You don’t need to be highly experienced with Docker to be able to take advantage of this feature. In fact, all you need to do is make sure Docker is installed and running on your machine. If you have done this and your project is appropriately configured, you are just a few clicks away from launching your new development environment.

Have fun and let me know your thoughts!


The Telegraph Engineering

The Telegraph Digital Engineering and Product team powering…


Written by


Software Engineer. Interested in web-technologies and open-source.

The Telegraph Engineering

The Telegraph Digital Engineering and Product team powering, The Telegraph mobile apps, Google AMP, Amazon echo Skills and Facebook articles


Written by


Software Engineer. Interested in web-technologies and open-source.

The Telegraph Engineering

The Telegraph Digital Engineering and Product team powering, The Telegraph mobile apps, Google AMP, Amazon echo Skills and Facebook articles

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store