Now that we understand the “why,” let’s get practical and learn “how” to set up Dev Containers in Visual Studio Code.
Installation and Prerequisites
Before embarking on your Dev Container journey, ensure you have the following prerequisites in place:
Docker
- Docker Desktop (Recommended): For Windows and macOS, Docker Desktop is the easiest way to get Docker running. Download and install it from https://www.docker.com/products/docker-desktop.
- Docker Engine (Linux): For Linux distributions, follow the installation instructions for your specific distribution from https://docs.docker.com/engine/install/.
- Verify Docker Installation: After installation, open your terminal and run
docker --versionanddocker compose version. You should see the installed versions printed. Ensure Docker is running in the background.
Configuration Notes for Docker
- Resource Allocation (Docker Desktop): Docker containers consume system resources. For optimal performance, especially with complex containers, consider increasing the resources allocated to Docker Desktop. You can adjust CPU, memory, and disk space in Docker Desktop’s settings.
- File Sharing (Docker Desktop on Windows): Ensure that the drive containing your project folder is shared with Docker Desktop. This is usually done during Docker Desktop installation or through its settings. This allows containers to access your project files.
Remote - Containers Extension
- Open Visual Studio Code.
- Go to the Extensions view (Ctrl+Shift+X or Cmd+Shift+X).
- Search for “Remote - Containers” by Microsoft.
- Click “Install” to install the extension.
Creating a Dev Container
With the prerequisites in place, let’s create our first Dev Container. The heart of Dev Containers is the devcontainer.json file. This file, placed in the .devcontainer folder at the root of your project, defines your containerized development environment.
- Open your Project Folder in Visual Studio Code: Open the root folder of your project in Visual Studio Code. If you don’t have a project yet, create an empty folder.
- Open the Command Palette: Press Ctrl+Shift+P (or Cmd+Shift+P on macOS) to open the Visual Studio Code Command Palette.
- Search for “Dev Containers”: Type “Dev Containers” and select “Dev Containers: Add Dev Container Configuration Files…“.
Choose a Predefined Container Definition or Create from Scratch
- Predefined Definition (Recommended for Beginners): Visual Studio Code offers a list of predefined Dev Container definitions for popular languages and frameworks (e.g., Node.js, Python, .NET, Go, Java). Choose one that closely matches your project’s technology stack.
- Create from ‘Empty Container’: If no predefined definition suits your needs, choose “From ‘Empty Container’“. This will create a basic
devcontainer.jsonthat you can customize from scratch. - Use ‘Dockerfile’: If you already have a Dockerfile for your project or want complete control, choose “From Dockerfile”. This will generate a
devcontainer.jsonthat references your existing Dockerfile.
- Customize
devcontainer.json(If needed): After selecting a definition, Visual Studio Code will create a.devcontainerfolder and placedevcontainer.jsoninside it. Opendevcontainer.jsonto review and customize its properties.
Key Properties of devcontainer.json
The image: This property specifies the Docker image to use as the base for your Dev Container.
- Example:
"image": "mcr.microsoft.com/devcontainers/javascript-node:18"(Uses a pre-built Node.js 18 image from Microsoft’s Dev Containers registry). - Usage: You can use pre-built images from public registries (like Docker Hub, mcr.microsoft.com), or your own custom images. Pre-built images are convenient for common environments, while custom images offer greater control and pre-configuration.
dockerFile: Instead ofimage, you can usedockerFileto specify the path to a Dockerfile within your project.- Example:
"dockerFile": "Dockerfile"(Assumes a Dockerfile namedDockerfilein the same.devcontainerfolder). - Usage: Use
dockerFilewhen you need to extensively customize the container environment beyond what pre-built images offer. Dockerfiles allow you to define every aspect of the container image.
context
When using dockerFile, this optional property specifies the build context for the Docker build. By default, it’s the same folder as the dockerFile. You can change it if needed.
Extensions
The extensions property is an array of Visual Studio Code extension IDs that should be automatically installed inside the Dev Container when it starts.
"extensions": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
]This ensures everyone using the Dev Container has the same set of extensions. Find extension IDs in the Visual Studio Code Marketplace URL or by right-clicking an extension in the Extensions view and selecting “Copy Extension ID”.
Settings
This settings property is a JSON object that allows you to define Visual Studio Code settings that will be applied inside the Dev Container.
"settings": {
"terminal.integrated.shell.linux": "/bin/bash",
"editor.formatOnSave": true
}Port Fowarding
The forwardPorts property is an array of ports that you want to forward from the container to your host machine.
For example, "forwardPorts": [3000, 8080, 5432] (Forwards ports 3000, 8080, and 5432 from the container to your host).
If your web application runs on port 3000 inside the container, forwarding port 3000 allows you to access it at http://localhost:3000 in your host browser.
Other Random Settings
workspaceFolder: Specifies the path inside the container where your project folder will be mounted. Defaults to /workspace. You usually don’t need to change this.
postCreateCommand: This property allows you to run shell commands once after the container is created and started for the first time.
- Example:
"postCreateCommand": "npm install"(Runsnpm installafter container creation to install project dependencies). - Usage: Use this to install project-specific dependencies, initialize databases, or perform other setup tasks that should run only once.
postStartCommand: Similar to postCreateCommand, but this command runs every time the Dev Container starts. Use with caution as frequent execution might impact startup time. Often used for starting background services or daemons needed for the development environment.
remoteUser: Specifies the user to connect to inside the container. Defaults to the user used when building the image or the Dockerfile’s USER instruction. You might need to change this if you require a specific user context.
An Example
{
"name": "Node.js Development Container",
"image": "mcr.microsoft.com/devcontainers/javascript-node:18",
"extensions": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode", "ms-vscode.js-debug-nodejs"],
"settings": {
"terminal.integrated.shell.linux": "/bin/bash",
"editor.formatOnSave": true,
"eslint.alwaysShowStatus": true
},
"forwardPorts": [3000],
"postCreateCommand": "npm install"
}