Skip to content

2026-01-01: Use devcontainers as the standard development environment for all projects

2026-01-01 Accepted

Setting up a new project locally has historically required developers to install language runtimes, package managers, databases, and other dependencies directly on their machines. This creates several problems:

  • Version mismatches between developers lead to “works on my machine” bugs.
  • Onboarding a new developer requires following a setup guide that can easily go out of date.
  • Switching between projects with conflicting runtime versions (e.g. different Node.js or Ruby versions) requires additional tooling such as nvm or rbenv.
  • CI environments and local environments tend to drift over time.

Alternatives considered:

  1. Document setup steps in a README and rely on host installs — the status quo. Setup guides go stale, and developer environments diverge silently.
  2. Use a managed cloud development environment (GitHub Codespaces, Gitpod) — adds cost and latency, and requires an internet connection to develop. Not suitable as the primary environment.
  3. Ship a Makefile or Taskfile that wraps Docker commands — reduces friction but does not provide an integrated editor environment; developers still need to configure their IDE manually.
  4. Use devcontainers — a Dev Container specification supported natively by VS Code (and other editors) that defines the full development environment as code, running inside Docker or Orbstack.

Every project in the organisation must include a devcontainer configuration. Docker or Orbstack is the only host requirement for developers.

Documentation-based setup is inherently brittle: steps are forgotten, versions drift, and new team members waste time debugging environment issues. The team spends maintenance effort on setup guides instead of the product.

Cloud development environments solve the same problem but introduce a hard dependency on internet connectivity and incur ongoing costs. They are a complement, not a replacement, for a reproducible local environment.

Why not Docker wrappers without devcontainers

Section titled “Why not Docker wrappers without devcontainers”

Running the application in Docker via a Taskfile reduces environment drift for the running process but leaves the developer’s editor, language server, and debug tooling configured against the host. Language-specific tools (linters, type checkers, formatters) must still be installed on the host in the correct version.

  • The full toolchain (language runtime, package manager, CLI tools) is defined in version-controlled configuration files, eliminating drift.
  • VS Code and compatible editors open the project inside the container and connect language servers, debuggers, and extensions to the container environment — no host-side language installs are needed.
  • Language runtimes are installed through devcontainer features, keeping the base image lean and the dependency declaration explicit.
  • A single host requirement (Docker or Orbstack) replaces a multi-step, error-prone setup guide.
  • The same container definition can be reused in CI, narrowing the gap between local and pipeline environments.
  • A broken environment can be fully reset by rebuilding the container, without any risk of corrupting the host machine’s configuration. This is a significant advantage in a team that regularly works with interns and apprentices who are not yet fluent with their development environment.
  • Developers must install Docker or Orbstack if not already present.
  • Container startup adds a small delay compared to a native process.
  • Developers unfamiliar with Docker or devcontainers need a short ramp-up period.
  • Resource usage (CPU, memory, disk) is higher than running processes natively.
  • Every project repository must contain a .devcontainer/devcontainer.json (or equivalent) that fully defines the development environment.
  • Docker or Orbstack is the only required host dependency for development. Language runtimes, package managers, and CLI tools must not need to be installed on the host.
  • Language runtimes must be installed via devcontainer features, not baked into a custom Docker base image.
  • All devcontainer definitions must include the standard features, extensions, settings, and mounts documented in guides/devcontainers.md.
  • Only application ports are forwarded to the host; backing-service ports (databases, caches, queues) must not be forwarded. See 2026-04-21: Only expose application ports in devcontainers.
  • Organisation-wide agent skills are made available inside devcontainers via a bind mount and a VS Code setting. See 2026-04-14: Syncing organisation-wide agent skills.
  • The onboarding guide for each project must be updated to reflect the devcontainer-first workflow.