Skip to content

Install and configure Dev Containers

Guaranteeing the integrity of a development environment can be sometimes tricky. In this tutorial, you will set up a Development Container with the Dev Containers extension that will guarantee you have the right Node.js (with npm) environment to perform all development steps that are described in this documentation.

This tutorial assumes that you have already followed the following tutorials. If you haven't, please follow them first.

Steps

Warning

Make sure to have Visual Studio Code and Docker installed. You can check the Install and configure Visual Studio Code and Install and configure Docker tutorials if needed.

Install useful extensions

First, you need to find the Dev Containers (ms-vscode-remote.remote-containers) extension in Visual Studio Code, for that you need to find it, and as Visual Studio Code documentation mentions:

Quote

You can browse extensions from within Visual Studio Code. Bring up the Extensions view by clicking on the Extensions icon in the Activity Bar on the left side of Visual Studio Code or use the shortcut command: View > Extensions.

Once you find it, you can install it.

Quote

To install an extension, select the Install button. Once the installation is complete, the Install button will change to the Manage gear button.

With the same process, you have to install the WSL (ms-vscode-remote.remote-wsl) too.

Create the working directory

First create an empty folder on your personal computer. Then open Visual Studio Code. Select File > Open Folder... on Visual Studio Code and select the empty folder you just created.

Open the distribution Ubuntu using the Start menu. This will open a command line in your distribution. Create a folder where you are going to do the tutorial:

mkdir create-a-media-player-application

And then go in that folder and launch Visual Studio Code

cd create-a-media-player-application
code .

Create a Dev Container

Open the Visual Studio Code command Palette with View > Command palette... and type the Dev Containers: Add Dev Container Configuration Files... command and select it.

Select Show All Definitions.. and type Node and select the container configuration template Node.js from csutter. Select the default image tag (18 when this tutorial was written). And then click on OK. Your working directory should looks like that.

1
2
3
4
.
└── .devcontainer
    ├── devcontainer.json
    └── Dockerfile

With the contents of the files as follow.

.devcontainer/devcontainer.json
1
2
3
4
5
6
7
8
// See https://containers.dev/implementors/json_reference/ for configuration reference
{
	"name": "A Node.js project",
	"build": {
		"dockerfile": "Dockerfile"
	},
	"remoteUser": "node"
}
.devcontainer/Dockerfile
FROM node:18

# Install basic development tools
RUN apt update && apt install -y less man-db sudo

# Ensure default `node` user has access to `sudo`
ARG USERNAME=node
RUN echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \
    && chmod 0440 /etc/sudoers.d/$USERNAME

# Set `DEVCONTAINER` environment variable to help with orientation
ENV DEVCONTAINER=true

Run the Dev Container

Open the Visual Studio Code command Palette with View > Command palette... and type the Dev Containers: Rebuild and Reopen in Container command and select it.

After running this command, when Visual Studio Code restarts, you're now within a Node.js dev container. Once you're connected, notice the green remote indicator on the left of the Status bar to show you are connected to your dev container.

Notice that the first time you open a container, it takes longer because it downloads the image of your container but when you will reopen the container, it will be faster, because the image is already download.

Try to upgrade npm

You can open a terminal in Visual Studio Code (with Terminal > New Terminal) and verify the Node.js and npm version. At the time of writing this tutorial, the versions are as follow. Yours might be more recent but it should work nonetheless.

In a Visual Studio Code terminal, execute the following command(s).
1
2
3
4
> npm --version
8.19.3
> node --version
v18.13.0

Now run the following command. Spoiler: it will fail.

In a Visual Studio Code terminal, execute the following command(s).
npm install --global npm@9.4.2

You can see that you can't execute that command, your user doesn't have enough permissions to execute it. You will modify your Dev Container to execute this code without using sudo.

Warning

Why is it a problem to install npm packages as root (with the help of the sudo command)? Using sudo, npm packages are installed globally on your system with access and permissions that could allow executing as malicious code as administrator. Modifying the npm configuration to install all your "global" packages as the local user in its home is a safer way.

Modify the Dev Container configuration

Open the Visual Studio Code command Palette with View > Command palette... and type the Dev Containers: Reopen Folder Locally command and select it.

Open the Visual Studio Code command Palette with View > Command palette... and type the Dev Containers: Reopen Folder In WSL command and select it.

You are not in the Dev Container anymore, a popup windows will appear asking you if you want to Reopen in Container, just ignore that call.

Create a npm-global-without-sudo.sh script in the .devcontainer folder.

1
2
3
4
5
.
└── .devcontainer
    ├── devcontainer.json
    ├── Dockerfile
    └── npm-global-without-sudo.sh
.devcontainer/npm-global-without-sudo.sh
#!/usr/bin/env bash
# https://github.com/sindresorhus/guides/blob/main/npm-global-without-sudo.md

mkdir "${HOME}/.npm-packages"

npm config set prefix "${HOME}/.npm-packages"

tee --append "${HOME}/.bashrc" > /dev/null <<EOT

NPM_PACKAGES="\${HOME}/.npm-packages"

export PATH="\$PATH:\$NPM_PACKAGES/bin"
EOT

Don't forget to make the script executable.

In a Visual Studio Code terminal, execute the following command(s).
chmod +x .devcontainer/npm-global-without-sudo.sh

Modify the .devcontainer/devcontainer.json as follow

.devcontainer/devcontainer.json
1
2
3
4
5
6
7
8
9
// See https://containers.dev/implementors/json_reference/ for configuration reference
{
	"name": "A Node.js project",
	"build": {
		"dockerfile": "Dockerfile"
	},
	"remoteUser": "node",
	"postCreateCommand": "./.devcontainer/npm-global-without-sudo.sh"
}

Run the Dev Container

Open the Visual Studio Code command Palette with View > Command palette... and type the Dev Containers: Rebuild and Reopen in Container command and select it.

And now, you can update npm without using sudo.

In a Visual Studio Code terminal, execute the following command(s).
npm install --global npm@9.4.2

Summary

Congrats! You have successfully configured and opened your first Dev Container environment!