Operations 10 min read

Dev Containers: The Ultimate Solution for Consistent Team Development Environments

This article explains how Dev Containers use Docker‑based configurations to give every team member an identical development environment—from OS dependencies to VS Code extensions—detailing core concepts, setup steps, sample devcontainer.json files for Python, Node, Go, and multi‑container stacks, plus best‑practice guidelines and CI/CD integration.

Ubuntu
Ubuntu
Ubuntu
Dev Containers: The Ultimate Solution for Consistent Team Development Environments

What is a Dev Container?

Core idea

传统开发环境问题:
┌─────────────┐   ┌─────────────┐   ┌─────────────┐
│ 开发者 A   │   │ 开发者 B   │   │ 开发者 C   │
│ Python 3.11│   │ Python 3.12│   │ Python 3.10│
│ Node 18    │   │ Node 20    │   │ Node 19    │
│ MySQL 8.0 │   │ PostgreSQL │   │ MariaDB   │
│ "能跑!"   │   │ 报错了 ❌   │   │ 缺包 ❌    │
└─────────────┘   └─────────────┘   └─────────────┘

Dev Container 方案:
┌─────────────┐   ┌─────────────┐   ┌─────────────┐
│ 开发者 A   │   │ 开发者 B   │   │ 开发者 C   │
│ ════════════ │   │ ════════════ │   │ ════════════ │
│ 同一个容器   ←─→│ 同一个容器   ←─→│ 同一个容器   │
│ 完全一致 ✅ │   │ 完全一致 ✅ │   │ 完全一致 ✅ │
└─────────────┘   └─────────────┘   └─────────────┘
        ↑               ↑               ↑
    devcontainer.json(定义在代码仓库中,版本管理)

How it works

你的项目仓库:
my-project/
├── .devcontainer/
│   └── devcontainer.json    ← 定义开发环境的"配方"
├── src/
└── README.md

团队成员操作:
git clone → VS Code 打开 →
F1 → "Dev Containers: Reopen in Container" →
自动构建 → 进入统一环境 ✅

Creating a devcontainer.json

Basic template

{
  "name": "My Project Dev Environment",
  "image": "mcr.microsoft.com/devcontainers/python:3.12",
  // "build": { "dockerfile": "Dockerfile" },
  "features": {
    "ghcr.io/devcontainers/features/node:1": {},
    "ghcr.io/devcontainers/features/docker-in-docker:2": {},
    "ghcr.io/devcontainers/features/common-utils:2": {}
  },
  "customizations": {
    "vscode": {
      "extensions": [
        "ms-python.python",
        "ms-python.vscode-pylance",
        "ms-python.black-formatter",
        "eamodio.gitlens",
        "PKief.material-icon-theme"
      ],
      "settings": {
        "python.defaultInterpreterPath": "/usr/local/bin/python",
        "editor.formatOnSave": true,
        "[python]": {
          "editor.defaultFormatter": "ms-python.black-formatter"
        }
      }
    }
  },
  "forwardPorts": [8000, 3000, 5000, 8080],
  "postCreateCommand": "pip install -r requirements.txt && echo '✅ Dev environment ready!'",
  "remoteUser": "vscode"
}

Common scenario configurations

Scenario 1: Python full‑stack project

{
  "name": "Python Full-Stack",
  "image": "mcr.microsoft.com/devcontainers/python:3.12",
  "features": {
    "ghcr.io/devcontainers/features/python:1": {"version": "3.12"}
  },
  "customizations": {
    "vscode": {
      "extensions": [
        "ms-python.python",
        "ms-python.vscode-pylance",
        "ms-python.debugpy",
        "charliermarsh.ruff",
        "mechatlinder.vscode-github-actions-io",
        "GitHub.copilot"
      ]
    }
  },
  "forwardPorts": [8000, 8888],
  "postCreateCommand": "pip install fastapi uvicorn sqlalchemy pytest httpie && pip install -r requirements.txt 2>/dev/null || true"
}

Scenario 2: Node.js frontend project

{
  "name": "Node.js Frontend",
  "image": "mcr.microsoft.com/devcontainers/javascript-node:20",
  "features": {
    "ghcr.io/devcontainers/features/node:1": {"version": "20"}
  },
  "customizations": {
    "vscode": {
      "extensions": [
        "dbaeumer.vscode-eslint",
        "esbenp.prettier-vscode",
        "bradlc.vscode-tailwindcss",
        "formulahendry.auto-rename-tag",
        "GitHub.copilot",
        "usernamehw.errorlens"
      ],
      "settings": {
        "node.autodetect": "on"
      }
    }
  },
  "forwardPorts": [3000, 5173],
  "postCreateCommand": "npm install"
}

Scenario 3: Go backend service

{
  "name": "Go Backend",
  "image": "mcr.microsoft.com/devcontainers/go:1.22",
  "features": {
    "ghcr.io/devcontainers/features/go:1": {}
  },
  "customizations": {
    "vscode": {
      "extensions": [
        "golang.Go",
        "gopls",
        "prempilot.devtools-yap"
      ]
    }
  },
  "forwardPorts": [8080, 3000],
  "remoteEnv": {
    "GOPATH": "/workspace/go",
    "PATH": "/usr/local/go/bin:/workspace/go/bin:${containerEnv:PATH}"
  },
  "postCreateCommand": "go mod download && go install github.com/air-verse/air@latest"
}

Scenario 4: Multi‑container stack (frontend + backend + database)

{
  "name": "Full Stack App",
  "dockerComposeFile": "docker-compose.yml",
  "service": "app",
  "workspaceFolder": "/workspace",
  "customizations": {
    "vscode": {
      "extensions": [
        "ms-python.python",
        "ms-python.vscode-pylance",
        "dbaeumer.vscode-eslint",
        "eamodio.gitlens"
      ]
    }
  },
  "forwardPorts": [8000, 3000, 5432, 6379]
}

Combine with docker-compose.yml:

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - ..:/workspace:cached
    command: sleep infinity
    depends_on:
      - db
      - redis
  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: dev
      POSTGRES_PASSWORD: dev
      POSTGRES_DB: appdb
    ports:
      - "5432:5432"
    volumes:
      - pgdata:/var/lib/postgresql/data
  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"
volumes:
  pgdata:

Usage in WSL

GUI steps

# Prerequisites:
# 1. Docker Desktop installed (WSL backend)
# 2. VS Code Remote - Containers extension installed

# Steps:
# 1. Open project folder in VS Code
# 2. Press F1 or Ctrl+Shift+P
# 3. Run "Dev Containers: Reopen in Container"
# 4. Choose configuration from devcontainer.json
# 5. Wait for build (first time downloads image)

Common Dev Container commands

Reopen in Container          # reopen inside container
Rebuild Container            # rebuild after devcontainer.json changes
Rebuild Without Cache         # full rebuild without cache
Attach to Running Container   # attach to an already running container
Show Container Logs          # view container logs
Clone Repository in Container # clone a repo directly inside the container

Feature ecosystem

node:1 – Node.js – npm, pnpm, nvm/fnm

python:1 – Python – pip, venv, common packages

go:1 – Go – go, gopls, delve

rust:1 – Rust – rustc, cargo, rust-analyzer

java:1 – Java – JDK, Maven, Gradle

docker-in-docker:2 – Docker – Docker CLI (nested)

common-utils:2 – General utilities – git, curl, jq, htop

github-cli:1 – GitHub CLI – gh command

aws-cli:1 – AWS CLI – aws command

terraform:1 – Terraform – IaC tool

Team collaboration practices

Version‑control devcontainer.json

my-repo/
├── .devcontainer/
│   ├── devcontainer.json   ← required for sharing
│   └── Dockerfile          (optional) custom build
├── src/
├── tests/
└── .gitignore             # exclude .devcontainer/cache/

Provide multiple configuration options

// .devcontainer/devcontainer.json          # default (lightweight)
// .devcontainer/devcontainer.full.json    # full (includes DB, etc.)
// .devcontainer/devcontainer.ci.json      # CI/CD configuration

CI/CD integration example

# .github/workflows/ci.yml (example)
jobs:
  test:
    runs-on: ubuntu-latest
    container:
      image: mcr.microsoft.com/devcontainers/python:3.12
    steps:
      - uses: actions/checkout@v4
      - run: pip install -r requirements.txt
      - run: pytest
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Dockerremote developmentVS CodeDev Containerscontainerized developmentdevcontainer.json
Ubuntu
Written by

Ubuntu

Focused on Ubuntu/Linux tech sharing, offering the latest news, practical tools, beginner tutorials, and problem solutions. Connecting open-source enthusiasts to build a Linux learning community. Join our QQ group or channel for discussion!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.