Self-hosted service
microsoft/vscode-remote-try-node avatar
microsoft/vscode-remote-try-node

vscode-remote-try-node is a teaching repo that happens to run a real Express app

Node.js sample project for trying out Dev Containers

837 stars810 forksJavaScriptMIT

At a glance

What is it?
The microsoft/vscode-remote-try-node sample exists to show what a dev container is, and it does that by shipping a small Node.js 26 on Debian 13 Express service with lint, debug and port forwarding wired up through .devcontainer/devcontainer.json.
Who is it for?
Use this repository if you want a five minute, disposable proof of what dev containers change about your editing and debugging loop, and do not treat it as a starting point for a production Node service, because the package is private, the app is a hello world and the repository carries no releases; before building on it, check the portsAttributes and onAutoForward values in .devcontainer/devcontainer.json and confirm which base image tag your environment can pull.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 6 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 25, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A sample whose purpose is the container, not the application

The repository description is short and honest: a Node.js sample project for trying out Dev Containers. The README defines the concept it exists to demonstrate, calling a development container a running container with a well-defined tool and runtime stack and its prerequisites. That definition is the lesson, and the code is the demonstration medium.

Two entry points are offered. GitHub Codespaces gives a hosted environment with a click on the Code drop-down menu, the Codespaces tab and Create codespace on main. Visual Studio Code Dev Containers runs the same thing locally through the Dev Containers extension, which will install itself if it is missing, clone the source into a container volume and start a container for use. The README points at a family of sibling sample repositories under the vscode-remote-try- prefix for other stacks.

So who is this for? Engineers who know what a Dockerfile is but have never edited code inside one, and teams who want to settle an argument about dev containers with something disposable. The value is the walkthrough rather than the artifact. The README even provides an escape hatch for readers who already have a Codespace or dev container, pointing them straight to the hands-on section.

Two ways to open the same code, and why the volume path matters

The VS Code route splits into two flows, and the difference between them is the interesting engineering detail. The first opens the repository in an isolated Docker volume: press F1, run Dev Containers: Try a Sample..., pick the Node sample and wait. The README explains that under the hood this uses the Dev Containers: Clone Repository in Container Volume... command, so the source lands on a Docker volume rather than the local filesystem, and it names volumes as the preferred mechanism for persisting container data.

The second flow works on a copy you already cloned locally. Clone the repository, press F1, choose Dev Containers: Open Folder in Container..., select the folder and wait for the container to start.

The volume route matters because it changes where your edits live and how they persist across rebuilds. A local clone mounts your working tree, which is comfortable but couples the container to host path permissions and file sharing behavior. The volume route isolates the checkout inside Docker storage, which the project presents as the preferred option. Either way the container definition comes from the .devcontainer directory in the repository root, so the toolchain is identical.

The toolchain is pinned by an image, a lint config and two npm scripts

The stack the sample runs on is stated plainly: Node.js 26 on Debian 13 (Trixie), Express 5 and ESLint 10. The base image is the mcr.microsoft.com/devcontainers/javascript-node image, and the README notes that the Node.js tools and extension metadata come from that image's labels. Extensions referenced in .devcontainer/devcontainer.json are installed automatically, which is why the Code Spell Checker appears without the reader installing anything.

The application itself is deliberately small. package.json names the package docker_web_app, marks it private, points main at server.js and declares exactly two scripts, with express as the only runtime dependency and the ESLint toolchain in devDependencies. The two commands a reader actually uses are short:

bash
npm run lint
npm start

The first runs the lint pass over the project, the second launches server.js. ESLint uses the flat configuration in eslint.config.mjs, which sits at the root of the repository alongside package-lock.json, package.json and server.js.

The inclusion of a package-lock.json matters more than it looks in a container demo, because it means the dependency tree resolved on the host is the tree that resolves inside the container.

Port 3000 and the devcontainer.json labels that make the Ports view readable

The sample listens on port 3000, and the README spends real effort on how that port gets surfaced. Run the app with F5 to launch it inside the container, hit a breakpoint set in server.js, and a notification reports that the service running on port 3000 is available. The Ports view gives an organized table of forwarded ports, reachable through the Ports: Focus on Ports View command, and clicking the globe icon there opens the service.

The label attached to port 3000 in that table is Hello Remote World, and the label is not hardcoded anywhere in the UI. It comes from devcontainer.json, where portsAttributes sets a label for forwarded ports along with the action taken when a port is autoforwarded. If the port number were unknown, the same attribute could match with a regex such as ".+/server.js" instead of the literal 3000.

There is one more detail worth internalizing. From a local browser you can reach the app at http://localhost:3000, but in a browser based Codespace you have to click the link from the notification or the Ports view, so the service handles port forwarding in the browser and generates the right URL. The same sample behaves differently in the two hosts, and the README explains why instead of leaving you to guess.

Rebuilding is how configuration changes reach the running container

Editing the container definition does not change a running container. The README is explicit that you rebuild when you change the setup, for instance installing a different software version or forwarding a new port. The worked example changes the portsAttributes in .devcontainer/devcontainer.json so the onAutoForward attribute reads openBrowser rather than notify, which makes the port open in a browser automatically instead of only raising a notification. Then F1 brings up Dev Containers: Rebuild Container or Codespaces: Rebuild Container so the modification is picked up.

The same rebuild step applies to the Dev Container Features mechanism. The README walks through adding the GitHub CLI by running Dev Containers: Configure Container Features... or Codespaces: Configure Container Features..., typing github in the filter box, ticking the GitHub CLI entry published by devcontainers, and confirming with OK before rebuilding the container.

That pattern of configure, then rebuild, then verify is the practical lesson of the whole repository. It also explains why the sample needs Docker installed locally and points at the getting started steps for prerequisites before anything else.

Why the sample cannot become your application

This repository is a fixture, and it shows in its metadata. The package is marked private, so it is not published to a registry, and the version field is the placeholder 1.0.0 with a placeholder author string. The dependency set is one runtime package. The whole point is to have something that starts in seconds so that you can watch the container mechanics work, and a project shaped like that has no room for real structure.

The second limit is scope of support. The repository carries no GitHub releases, so there is no versioned artifact to pin and no upgrade stream to track. The last push was on 2026-10-10 and the repository is not archived, which means the code moves, but a sample repository is updated when the sample needs refreshing rather than on a support schedule. Treat any change you make to it as your own fork.

The third limit is the licensing of everything around it. The repository itself carries an MIT LICENSE file, which is permissive, but the container you end up running is built from the mcr.microsoft.com/devcontainers/javascript-node image, and the extensions pulled in, including the Code Spell Checker and the ESLint extension, carry their own terms. Mixing an MIT repository with image and extension licenses is normal in the container world and worth checking against your own policy before the pattern spreads.

What the walkthrough actually teaches an engineer

Strip away the sample app and the repository teaches four things that generalize to any stack.

First, that a dev container is described as data rather than as a script: a base image, a set of extensions and features, and some port metadata, all in a .devcontainer directory that lives in the repository. Second, that the editing loop does not change once you are inside. The README says you will be able to work with the sample like you would locally, and the editing exercise, with the spell checker catching a deliberate mistake, exists to prove that language services work correctly against a container filesystem.

Third, that debugging crosses the boundary. A breakpoint in server.js, F5 to launch in the container, then hovering variables and examining locals once the breakpoint hits, all with the runtime inside the container rather than on the host.

Fourth, that the container can be extended after the fact through Features without a rebuild of the base image, provided you accept that a rebuild is required for any of it to take effect. Teams that want the same experience for their own services can point the same mechanism at a repository that has a real build and a real dependency tree.

Editorial conclusion

Use this repository if you want a five minute, disposable proof of what dev containers change about your editing and debugging loop, and do not treat it as a starting point for a production Node service, because the package is private, the app is a hello world and the repository carries no releases; before building on it, check the portsAttributes and onAutoForward values in .devcontainer/devcontainer.json and confirm which base image tag your environment can pull.

Frequently asked questions

How do I open vscode-remote-try-node in a dev container?

Press F1 in Visual Studio Code and run Dev Containers: Try a Sample..., then choose the Node sample and wait for the container to start. That path clones the source into a Docker volume rather than the local filesystem, and it needs Docker installed.

What runtime and libraries does the vscode-remote-try-node sample use?

The README states that the sample uses Node.js 26 on Debian 13 (Trixie), Express 5 and ESLint 10, with Express as the only runtime dependency in package.json. The container is based on the mcr.microsoft.com/devcontainers/javascript-node image.

How do I change the container configuration in vscode-remote-try-node?

Edit .devcontainer/devcontainer.json, for example changing the onAutoForward attribute in portsAttributes from notify to openBrowser, then run Dev Containers: Rebuild Container or Codespaces: Rebuild Container. Rebuilding is what makes the change take effect.

Can I add tools to the vscode-remote-try-node container after it starts?

Yes, through container features. Run Dev Containers: Configure Container Features... or Codespaces: Configure Container Features..., type github in the filter, tick the GitHub CLI entry published by devcontainers and confirm, then rebuild the container.

Official sources

  1. Issues
  2. License: MIT
  3. microsoft/vscode-remote-try-node on GitHub
  4. Project website
  5. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/microsoft-vscode-remote-try-node.svg)](https://hysenlabs.com/projects/microsoft-vscode-remote-try-node)

Was this useful?