Skip to main content
← All Tools · 🛠️ Documentation & DX Tools

Dev Containers — Reproducible Development Environments in Docker

VS Code Dev Containers — define your entire development environment in a JSON file, run it in Docker, and get identical setups across your team.

Free Open source spec; free with VS Code, GitHub Codespaces (free tier: 60h/month)
developer-toolsdockervscodedevexenvironmentscontainerscodespaces

✅ Pros

  • + Reproducible environments — 'works on my machine' becomes 'works in the container'
  • + One-click setup — new hires clone repo and run, no setup docs needed
  • + Works with GitHub Codespaces for cloud development
  • + Lifecycle hooks: `postCreateCommand`, `postStartCommand` for automated setup
  • + Feature library: pre-built features for Node, Python, AWS CLI, kubectl, etc.

⚠️ Cons

  • − Requires Docker running locally — overhead on less powerful machines
  • − First build can be slow (pulling images, installing tools)
  • − Volume mounts on Windows/macOS slower than native Linux
  • − Container rebuild needed when devcontainer.json changes

Overview

Dev Containers define your development environment as code. Instead of a long README of setup steps, a .devcontainer/devcontainer.json file specifies the Docker image, VS Code extensions, port forwarding, and environment setup scripts. Anyone on the team (or GitHub Codespaces) opens the repo and gets an identical, ready-to-code environment.

Basic Configuration

// .devcontainer/devcontainer.json
{
  "name": "Node.js & TypeScript",
  "image": "mcr.microsoft.com/devcontainers/typescript-node:1-20-bookworm",

  "features": {
    "ghcr.io/devcontainers/features/github-cli:1": {},
    "ghcr.io/devcontainers/features/docker-in-docker:2": {},
    "ghcr.io/devcontainers/features/aws-cli:1": {}
  },

  "forwardPorts": [3000, 5432, 6379],

  "postCreateCommand": "npm install",
  "postStartCommand": "npm run db:migrate",

  "customizations": {
    "vscode": {
      "extensions": [
        "dbaeumer.vscode-eslint",
        "esbenp.prettier-vscode",
        "ms-azuretools.vscode-docker"
      ],
      "settings": {
        "editor.formatOnSave": true,
        "editor.defaultFormatter": "esbenp.prettier-vscode"
      }
    }
  }
}

Full Stack with Docker Compose

For apps that need multiple services (app + database + cache):

# .devcontainer/docker-compose.yml
services:
  app:
    build:
      context: ..
      dockerfile: .devcontainer/Dockerfile
    volumes:
      - ../..:/workspaces:cached
    command: sleep infinity  # VS Code attaches here

  postgres:
    image: postgres:16
    environment:
      POSTGRES_DB: myapp_dev
      POSTGRES_USER: dev
      POSTGRES_PASSWORD: devpassword
    volumes:
      - postgres-data:/var/lib/postgresql/data

  redis:
    image: redis:7-alpine

volumes:
  postgres-data:
// .devcontainer/devcontainer.json (with compose)
{
  "name": "Full Stack Dev",
  "dockerComposeFile": "docker-compose.yml",
  "service": "app",
  "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
  "postCreateCommand": "npm install && npm run db:migrate"
}

Using Features

Features are reusable dev environment components:

{
  "features": {
    "ghcr.io/devcontainers/features/node:1": {
      "version": "20"
    },
    "ghcr.io/devcontainers/features/python:1": {
      "version": "3.12"
    },
    "ghcr.io/devcontainers/features/kubectl-helm-minikube:1": {
      "version": "latest"
    }
  }
}

Browse 100+ official features at containers.dev/features.

GitHub Codespaces

The same devcontainer.json powers GitHub Codespaces — a full VS Code environment in the browser:

# From any GitHub repo: press . (period) for quick editor
# Or: Code → Codespaces → Create codespace on main

# Free tier: 60 hours/month of 2-core machines

This means contributors never need to install anything locally — they open a Codespace and start coding immediately.

Best For

  • Teams with complex local setup — projects requiring specific Node/Python versions, databases, Redis, or external services that take hours to set up manually
  • Open-source projects wanting zero-friction contributor onboarding — add a devcontainer and contributors start coding in minutes, not hours
  • Enterprise teams on Windows where inconsistent WSL setups cause “works on my machine” problems
  • Bootcamps and courses — students all get identical environments without debugging 10 different laptop configurations
  • Regulated environments where exact dependency versions must be auditable and reproducible

Dev Containers vs. Alternatives

Dev ContainersDocker + MakefileNixVagrant
IDE integrationDeep (VS Code, JetBrains)ManualPartialManual
Setup speedFast (pull image)MediumSlow (first build)Slow
GitHub Codespaces✅ Native✗✗✗
Learning curveLowLowHighMedium
Best forVS Code teams, OSS projectsAny CI setupNixOS users, reproducibility puristsMulti-VM setups

Dev Containers have the best IDE integration and Codespaces support. For projects that need reproducible builds in CI but not local dev, a plain Dockerfile + Makefile is simpler.

Concrete Use Case: Onboarding 10 Engineers in One Week with Zero Setup Friction

A growing fintech startup needed to onboard 10 new backend engineers in a single week. Their stack — a Python 3.12 monorepo with FastAPI, PostgreSQL 16, Redis, and Celery — required installing 14 tools locally, configuring database schemas, seeding test data, and setting up three .env files. Previous onboarding averaged 1.5 days per engineer, with at least one “works on my machine” blocker per person (usually a mismatched PostgreSQL version or missing system-level C library for a Python dependency). The engineering lead decided to invest one day building a Dev Container configuration before the cohort arrived.

The .devcontainer/ directory included a docker-compose.yml spinning up the app container (based on mcr.microsoft.com/devcontainers/python:3.12), PostgreSQL 16, and Redis 7. The devcontainer.json used postCreateCommand to run pip install -e ".[dev]" && alembic upgrade head && python scripts/seed_test_data.py, ensuring that by the time VS Code opened, the database was migrated and seeded. Features pulled in the AWS CLI, GitHub CLI, and Docker-in-Docker for running integration tests. VS Code settings auto-installed the Python, Pylance, and GitLens extensions with the team’s shared settings.json for consistent formatting and type-checking behavior.

On day one, each new engineer cloned the repo, opened it in VS Code, clicked “Reopen in Container,” and had a fully working environment in under 4 minutes. The engineers using GitHub Codespaces (two were on company-issued Chromebooks) got the same experience in the browser. Zero setup tickets were filed that week. The Dev Container config became a living document — when the team later added a Kafka dependency, they added a Kafka service to the compose file, and every developer got it on their next container rebuild. The total onboarding time dropped from 1.5 days to 15 minutes, and “works on my machine” incidents dropped to zero for the quarter.

When to Use Dev Containers

Use Dev Containers when:

  • Your project has complex environment requirements (specific language versions, databases, system libraries) that are painful to install manually
  • You onboard new team members frequently and want to eliminate setup documentation that goes stale
  • Your team works across different operating systems (Windows, macOS, Linux) and you need consistent behavior everywhere
  • You want to enforce identical tooling versions across the team (linter versions, formatter configs, CLI tools) without relying on each developer to maintain them
  • You use GitHub Codespaces and want the same environment locally and in the cloud

When NOT to use Dev Containers:

  • Your project is a single-file script or simple CLI tool with no external dependencies — the Docker overhead is not justified
  • Your team works exclusively on high-performance native development (game engines, GPU-intensive ML training) where Docker’s I/O and GPU passthrough limitations are deal-breakers
  • Developers on your team have low-spec machines (under 8GB RAM) where running Docker Desktop alongside an IDE causes constant swapping
  • Your organization prohibits Docker on developer workstations for security policy reasons and does not use GitHub Codespaces