Building VS Code Extensions in Docker Containers

Posted on Fri 23 February 2018 in Editors • 3 min read

TL;DR:

  • VS Code is an editor that allows you to write and share custom extensions.

  • These extensions require Node.js and npm installed, which you might not want to install locally - especially given recent, scary issues.

  • Instead, using the Dockerfile and commands below, you can build extensions inside a Docker container and still test and run them inside the VS Code installation on the same machine without Node installed.

Background

I’ve been using VS Code as my main editor for personal work for some time now, but only just got around to trying to create an extension.

I don’t do any Node or Javascript development normally, so don’t have Node/NPM installed, and that’s the first thing the docs tell you to do. Keen not to install these on my system given the bloat I’ve heard they add and recent issues, I wanted to do try and do the necessary generation and building in a container.

Searching online for various combinations of relevant keywords only seemed to give me articles on writing extensions to work with Docker files/containers, and I had to poke about and get this working myself. I thought I’d write up how I did it in case it’s useful for someone else.

Getting Started

Obviously you’ll need docker installed and set up.

Then the following Dockerfile will allow you to create a container with the VS Code extension generator ready and installed.

FROM node:latest

RUN npm install -g yo generator-code

USER node
WORKDIR /home/node/

ENTRYPOINT bash

Create a copy of that Dockerfile and build it - I called it vscodeextenv:

sudo docker build -t vscodeextenv .

Now I created a directory ready and named for my extension, and mounted that into the container.

mkdir example
sudo docker run -it \
     --mount source=$(pwd)/example,target=/home/node/example,type=bind \
     vscodeextenv

Now you should have an environment ready to build an extension.

Gotcha: I found out that docker now recommends you use --mount to mount directories inside a container rather than -v, but using that ended up with the mounted directory inside the container being owned by root until I added type=bind to the mount option.

Building the Extension

Here you can just run the extension generator with yo code and follow the prompts. I named mine example, and just used dummy values for everything else. Like a good developer I also turned on all the linting 😉.

Once it’s generated, the docs say to start debugging the extension, but from what I can tell that first builds the extension, which won’t work since we don’t have all the dependencies installed. If I try, I get a few errors/stack traces in the debug console and this notification in the original VS Code instance

Alt Text

The second instance that’s supposed to have the extension loaded does open, but doesn’t have it loaded in.

So we need to build it manually first.

This might be obvious if you’re a proficient node developer, but after some poking through the generated files I found the command - in the container, run:

npm run compile

You’ll now have an out directory, which is what VS Code needs.

Gotcha: For me the compile command failed with an error I think because I enabled the various linting and strict options when generating the project - this is fixed for now by commenting these lines out in src/test/extension.test.ts

// import * as vscode from 'vscode';
// import * as myExtension from '../extension';

Testing the extension in VS Code

Now you should be able to, in VS Code, just open the Debug tab and press the Play button, and the new instance of VS Code with your app loaded should appear!

If you’ve just used the default app, then Ctrl+Shift+P in the new instance should allow you to find the hello world command, and running it should correctly show the notification.

The only downsides are that:

  • the original VS Code instance still shows the error in the image above (I think because it still tries to build the extension and fails), though it runs fine regardless,

  • you have to remember to manually build the extension in the container before running it in the VS Code debugger.