Remote development: SSH, containers, WSL

VS Code · Expert · 15 min

Remote development gives you local-feeling editing on the machine where code actually runs, and reproducible environments for teams.

VS Code is split into a UI (the window) and a backend that does file access, terminals, language servers and debugging. The Remote extensions move the backend elsewhere by installing a VS Code Server there:

  • Remote - SSH: connect to any SSH host from your ~/.ssh/config; files, terminals and extensions run on the server.
  • Dev Containers: open a folder inside a Docker container defined by .devcontainer/devcontainer.json.
  • WSL: develop inside a Linux distribution on Windows.
  • Remote Tunnels (code tunnel on the remote machine) work without SSH access, through a Microsoft-relayed tunnel, and also from vscode.dev in a browser.

Extensions have a kind: UI extensions (themes, keymaps) stay local, while workspace extensions (language servers, linters, debuggers) must be installed on the remote side, which VS Code does per host or container. Ports opened by remote processes are forwarded to localhost automatically.

A devcontainer.json makes the environment reproducible: base image or Dockerfile, features (prebuilt tool installs such as Node or the GitHub CLI), extensions and settings to install, forwardPorts, and lifecycle commands like postCreateCommand. Commit it and every developer, plus GitHub Codespaces, gets the same toolchain with "Reopen in Container".

When something breaks, the Output channel "Remote - SSH" or "Dev Containers" shows the server installation and connection log.

Example

// .devcontainer/devcontainer.json
{
  "name": "shop-api",
  "image": "mcr.microsoft.com/devcontainers/python:3.12",
  "features": {
    "ghcr.io/devcontainers/features/node:1": { "version": "22" },
    "ghcr.io/devcontainers/features/github-cli:1": {}
  },
  "forwardPorts": [8000],
  "postCreateCommand": "pip install -r requirements.txt",
  "customizations": {
    "vscode": {
      "extensions": ["ms-python.python", "charliermarsh.ruff"],
      "settings": { "python.defaultInterpreterPath": "/usr/local/bin/python" }
    }
  }
}
// Command Palette: "Dev Containers: Reopen in Container"
// or "Remote-SSH: Connect to Host..." (hosts come from ~/.ssh/config)

Remember

  • The backend (VS Code Server) runs remotely; the UI stays local
  • Workspace extensions install on the remote side, UI extensions stay local
  • devcontainer.json defines a reproducible environment, also used by Codespaces

Watch out for

  • Installing a linter extension locally and wondering why it does nothing in a remote window; install it in the remote.

Check yourself

  1. In a Remote - SSH window, where does a language server extension like Pylance run?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: code.visualstudio.com/docs/remote/remote-overview

Builds on

Unlocks

Nothing builds on this yet.