Anthony Chu Contact Me

Experiment with New Languages and Frameworks with VS Code Remote Development in Containers

Monday, July 8, 2019

In April, Visual Studio Code launched their new Remote Development extensions. With VS Code Remote Development, a VS Code instance on our local machine can access and use a container, remote machine, or Windows Subsystem for Linux (WSL) as a full-featured development environment.

I've been using all three flavors of VS Code Remote Development and they each unlock some really exciting scenarios. Today, we'll look at how VS Code Remote with containers allows us to experiment with new languages and frameworks without installing any new tools or SDKs on our machines.

The specific scenario we'll look at is to use a container to test out the latest nightly build of ASP.NET Core 3.0 (currently Preview 7).

Setting up VS Code

To get our VS Code ready for remote development, we need to search for and install the Remote Development extension pack. It needs the latest version of VS Code.

Install extension

Starting a container

We want to test out the nightly builds of .NET Core. We could find the right version and install it on our local machine. Although .NET Core supports side-by-side installation, this still feels a bit risky. It would be much better if we can spin up a temporary environment to experiment in and we can delete it when we're done.

A great way of spinning up temporary environments is Docker containers. Many stacks have prebuilt container images on Docker Hub or some other public registry that we can just pull down and use. .NET Core ships Docker images of their nightly builds to the Microsoft Container Registry (MCR). We can browse the different tags available by going to Docker Hub.

The image we're going to use is dotnet/core-nightly/sdk:3.0, which is the latest nightly build of the 3.0 SDK (currently it's 3.0.100-preview7) on Debian.

To run it, we can run the following command in a terminal:

docker run -it --name dotnet3-nightly-test mcr.microsoft.com/dotnet/core-nightly/sdk:3.0 bash

We've given the container a name of dotnet3-nightly-test and started a bash shell. We can use the shell to check the dotnet version (dotnet --version), but what we really want to do is to use it from VS Code.

Attach VS Code

We'll keep the terminal open so that the container continues to run. Open up an instance of VS Code.

There are a couple of ways to connect to the container. One is to run "Remote-Containers: Attach to Running Container" in the command palette. If we have the VS Code Docker extension installed, we can also right-click the running container in the extension and select "Attach Visual Studio Code".

Attach VS Code

VS Code will attach to the container and configure it for remote development (it installs a VS Code server in the container).

In the VS Code instance that is attached to the container, open a terminal. This terminal is running inside the container.

Attach VS Code

Create an app

Now we're ready to build an app. The first thing we want to do is create a folder and scaffold an app. In the VS Code remote terminal, create a folder and scaffold an ASP.NET app. We'll use a Blazor app here:

mkdir app
cd app
dotnet new blazorserverside

Now that the app is created, we can use File > Open in the menu to select our app folder. VS Code will reopen in that folder and we can see the files in the Explorer view.

Install extensions

Notice that while there is syntax highlighting and simple completion in the C# files, it doesn't show errors or provide IntelliSense completion as we type. To fix this, we need to install the C# extension inside the container. We can do this by searching for the "C#" in the Extensions pane. It gives us an option to "Install on Attached Container"; click it to install it.

Install C# extension

Once the extension is installed, it prompts us to reload the VS Code instance. Once reloaded, it'll take a minute to install the OmniSharp language server. When it's done, the extension will prompt us to install the required assets to run the application.

Enable debugging

Click Yes. It will set up the .vscode folder with the launch configuration to debug our app.

Run and debug the app

Now we can press "F5" to start debugging our application.

We'll see the browser opens but there's an error. This is because, by default, our VS Code is configured to launch the browser to the HTTPS endpoint of our app and our machine doesn't trust the self-signed cert.

Error

To fix this, we can force the app to HTTP only when running in VS Code. To do this, open .vscode/launch.json and add an envionment variable named ASPNETCORE_URLS with value of http://localhost:5000. This ensures the app starts with a single unsecured HTTP endpoint.

"env": {
  "ASPNETCORE_ENVIRONMENT": "Development",
  "ASPNETCORE_URLS": "http://localhost:5000"
}

Now when we run the app with "F5", the browser opens and it works!

Works!

Note that if you want to run the app in the container with HTTPS enabled, you can follow the instructions here.

How is this working?

If we look more closely at launch.json, we'll notice a section that tells VS Code to start a browser:

"serverReadyAction": {
  "action": "openExternally",
  "pattern": "^\\s*Now listening on:\\s+(https?://\\S+)"
}

The pattern is a regular expression that extracts the URL from the application output and VS Code opens it in a browser. In our case, it's http://localhost:5000.

Notice that the browser is opened to a seemingly random port, even though we told the app to start on port 5000. This is because we didn't tell Docker to open port 5000 when we started the container. So VS Code is dynamically allocating a port on our machine and proxying traffic to port 5000 inside the container. It's all magic!

Delete the container

When we're done, we just need to close VS Code and exit our container in the terminal. If we want to start the environment again, just start the container and re-attach VS Code.

And we can delete the container when we don't need it anymore.

Other ways to use remote containers

What we went through was just one way of using VS Code Remote containers. If we have a project that we want to run inside a specially built container, we can add a devcontainer.json file and a Dockerfile to our project. To learn how to do this, check out the documentation.

And to learn all about VS Code Remote Development, see its full documentation.