TL;DR
Dev Containers 使用 devcontainer.json 文件将整个开发环境定义为代码,确保每个开发者一键获得完全相同的可复现环境。2026 年已被 VS Code、JetBrains、GitHub Codespaces 和 CI/CD 流水线原生支持,通过容器化编辑器设置、扩展、工具、运行时和服务来消除"在我机器上能跑"的问题。
Key Takeaways
- devcontainer.json 是被 VS Code、JetBrains、GitHub Codespaces 和 CLI 工具支持的开放规范
- mcr.microsoft.com/devcontainers 的预构建镜像覆盖大多数语言
- Features 系统让你无需编写 Dockerfile 即可组合工具
- Docker Compose 集成支持包含数据库和缓存的多服务开发环境
- GitHub Codespaces 提供可从浏览器访问的云端开发容器
- 生命周期命令自动化依赖安装和服务启动
- GPU 直通支持在容器内进行 ML/AI 开发
- devcontainer CLI 让 CI/CD 流水线使用与开发者本地相同的环境
Table of Contents
- 什么是 Dev Containers
- Dev Containers vs Docker Compose vs Vagrant vs Nix
- devcontainer.json 规范
- VS Code 设置
- GitHub Codespaces
- 预构建镜像
- 自定义 Dockerfile
- Features 系统
- Docker Compose 多服务
- 端口转发
- 环境变量和密钥
- VS Code 扩展和设置
- 生命周期命令
- 卷和挂载
- GPU 支持 ML/AI
- 多根工作区
- 模板和社区 Features
- JetBrains 支持
- 性能优化
- 团队入职
- CI/CD 集成
- 安全最佳实践
- 常见语言模式
- 故障排查
"在我机器上能跑"的问题困扰软件团队数十年。不同的操作系统、工具版本和系统配置导致构建失败和入职耗时数天。Dev Containers 通过将整个开发环境定义为仓库中的单个 JSON 文件来解决这个问题。2026 年,该规范已成为被每个主要编辑器和云平台支持的开放标准。
什么是 Dev Containers 以及为什么重要
Dev Container 是专为开发配置的 Docker 容器。与生产容器不同,它包含编辑器、调试器、语言运行时和所有开发工具。配置在 .devcontainer/devcontainer.json 中,可版本控制并在团队中共享。
为什么 Dev Containers 在 2026 年很重要
- 零入职摩擦:新成员几分钟内获得可工作的环境
- 可复现构建:所有人运行相同的工具和版本
- 操作系统独立:相同配置在 macOS、Windows 和 Linux 上工作
- 云端就绪:本地运行或在 GitHub Codespaces 中即时启动
- 开放规范:被 VS Code、JetBrains、DevPod 等支持
- CI/CD 一致性:在与开发者相同的容器中测试和构建
Dev Containers vs Docker Compose vs Vagrant vs Nix
Dev Containers 不是唯一的可复现环境方案。以下是 2026 年的对比。
| Feature | Dev Containers | Docker Compose | Vagrant | Nix |
|---|---|---|---|---|
| Purpose | Dev environment as code | Multi-container orchestration | VM-based dev environments | Reproducible packages |
| Editor Integration | VS Code, JetBrains native | None | SSH only | direnv + plugins |
| Cloud Support | Codespaces, DevPod | None | None | None |
| Startup Speed | Seconds (cached) | Seconds | Minutes (VM) | Seconds (cached) |
| Resource Usage | Low (containers) | Low (containers) | High (full VM) | Minimal (host) |
| Learning Curve | Low-Medium | Medium | Medium | High |
| Multi-Service | Via Docker Compose | Native | Multiple VMs | NixOS containers |
| OS Isolation | Linux container | Linux container | Full VM (any OS) | None (host) |
devcontainer.json 规范和结构
devcontainer.json 是每个 Dev Container 的核心,遵循 containers.dev 的开放规范,位于 .devcontainer/devcontainer.json。
// .devcontainer/devcontainer.json — full reference
{
"image": "mcr.microsoft.com/devcontainers/typescript-node:20",
// OR: "build": { "dockerfile": "Dockerfile", "context": ".." },
// OR: "dockerComposeFile": "docker-compose.yml", "service": "app",
"name": "My Project Dev",
"features": {
"ghcr.io/devcontainers/features/node:1": { "version": "20" },
"ghcr.io/devcontainers/features/python:1": { "version": "3.12" },
"ghcr.io/devcontainers/features/docker-in-docker:2": {}
},
"forwardPorts": [3000, 5432, 6379],
"portsAttributes": {
"3000": { "label": "App", "onAutoForward": "notify" },
"5432": { "label": "PostgreSQL", "onAutoForward": "silent" }
},
"customizations": {
"vscode": {
"extensions": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode"],
"settings": { "editor.formatOnSave": true }
}
},
"containerEnv": { "NODE_ENV": "development" },
"remoteEnv": { "LOCAL_USER": "\${localEnv:USER}" },
"postCreateCommand": "npm install && npx prisma migrate dev",
"postStartCommand": "npm run dev",
"remoteUser": "node",
"mounts": [
"source=node-modules,target=/workspace/node_modules,type=volume",
"source=\${localEnv:HOME}/.ssh,target=/home/node/.ssh,type=bind,readonly"
],
"runArgs": ["--memory=4g", "--cpus=2"]
}VS Code Dev Containers 扩展设置
VS Code 通过 Dev Containers 扩展提供一流支持。安装后可检测项目中的 devcontainer.json 并提供在容器内重新打开的选项。
The extension requires Docker Desktop (or Docker Engine on Linux) to be installed and running. On macOS and Windows, Docker Desktop provides the Docker daemon and a Linux VM for running containers. On Linux, Docker Engine runs natively with the best performance.
# Step 1: Install prerequisites
# macOS/Windows: Install Docker Desktop from docker.com
# Linux: Install Docker Engine
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
# Step 2: Install the Dev Containers extension
code --install-extension ms-vscode-remote.remote-containers
# Step 3: Verify Docker is running
docker --version # Docker 24+ recommended
docker info # Verify Docker daemon is active
# Step 4: Open project — VS Code detects devcontainer.json
code /path/to/project
# Click "Reopen in Container" notification
# Or: Ctrl+Shift+P > "Dev Containers: Reopen in Container"
# Key commands (Command Palette):
# Dev Containers: Rebuild Container — after config changes
# Dev Containers: Rebuild Without Cache — force clean build
# Dev Containers: Reopen Folder Locally — exit container mode
# Dev Containers: Show Container Log — debug build issues
# Dev Containers: Open Folder in Container — open any folder
# Dev Containers: Clone Repository in Container Volume — faster I/OGitHub Codespaces 集成
GitHub Codespaces 提供可从任何仓库启动的云端开发容器,读取 devcontainer.json 在云端构建环境,通过浏览器或本地 VS Code 访问。
# Create a Codespace:
# 1. Go to repo on GitHub > Code > Codespaces > Create codespace
# Machine types (2026):
# 2-core / 8GB — free tier (120 hrs/month)
# 4-core / 16GB — \$0.36/hr
# 8-core / 32GB — \$0.72/hr
# 16-core / 64GB — \$1.44/hr
# 32-core / 128GB — \$2.88/hr (GPU available)
# Prebuilds: Settings > Codespaces > Set up prebuild
# Reduces Codespace startup to seconds
# Secrets: GitHub > Settings > Codespaces > Secrets
# Available as env vars, never committed to source预构建的 Dev Container 镜像
Microsoft 在 mcr.microsoft.com/devcontainers 提供预构建镜像,针对开发容器优化,包含常用工具并定期安全更新。
| Image | Includes | Size |
|---|---|---|
| devcontainers/base:ubuntu | Git, curl, zsh, utilities | ~350MB |
| devcontainers/typescript-node:20 | Node.js 20, npm, yarn, TypeScript | ~650MB |
| devcontainers/python:3.12 | Python 3.12, pip, venv | ~600MB |
| devcontainers/go:1.22 | Go 1.22, gopls, delve | ~800MB |
| devcontainers/rust:1 | Rust, cargo, clippy | ~1.2GB |
| devcontainers/java:21 | JDK 21, Maven, Gradle | ~900MB |
| devcontainers/universal:2 | Node, Python, Java, Go, .NET, PHP, Ruby | ~6GB |
自定义 Dockerfile
当预构建镜像不满足需求时,提供自定义 Dockerfile。devcontainer.json 引用它,VS Code 在启动前构建镜像。
When writing a Dockerfile for dev containers, start from a devcontainers base image whenever possible. These images already include common utilities like git, curl, sudo, and zsh. Then add your project-specific system packages, language runtimes, and global tools. Keep the image focused on development needs, not production requirements.
# .devcontainer/Dockerfile
FROM mcr.microsoft.com/devcontainers/base:ubuntu
# Install system dependencies for native compilation
RUN apt-get update && apt-get install -y \
build-essential \
libpq-dev \
libssl-dev \
pkg-config \
protobuf-compiler \
graphviz \
&& rm -rf /var/lib/apt/lists/*
# Install Node.js 20
RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
&& apt-get install -y nodejs
# Install global npm packages
RUN npm install -g pnpm@9 turbo@2 tsx
# Install Rust toolchain (optional for projects using native modules)
RUN curl --proto "=https" --tlsv1.2 -sSf https://sh.rustup.rs | \
sh -s -- -y --default-toolchain stable
ENV PATH="/root/.cargo/bin:\${PATH}"
# Create non-root user workspace
WORKDIR /workspace// .devcontainer/devcontainer.json with custom Dockerfile
{
"name": "Custom Dev Environment",
"build": {
"dockerfile": "Dockerfile",
"context": "..",
"args": {
"NODE_VERSION": "20",
"VARIANT": "bookworm"
},
"cacheFrom": "ghcr.io/myorg/devcontainer:latest"
},
"remoteUser": "vscode",
"postCreateCommand": "npm install"
}Features 系统:安装工具和语言
Features 是可组合的安装代码单元。无需编写 Dockerfile RUN 命令,在 devcontainer.json 中添加 Features 即可自动处理安装和版本固定。
Features are distributed as OCI artifacts (container images) and follow a well-defined installation protocol. Each Feature includes a devcontainer-feature.json manifest and an install.sh script. The official Features repository at github.com/devcontainers/features covers the most common tools, while community Features at github.com/devcontainers-contrib/features extend coverage to hundreds of additional tools.
// Popular Dev Container Features (2026)
{
"features": {
// Language runtimes
"ghcr.io/devcontainers/features/node:1": { "version": "20" },
"ghcr.io/devcontainers/features/python:1": { "version": "3.12" },
"ghcr.io/devcontainers/features/go:1": { "version": "1.22" },
"ghcr.io/devcontainers/features/rust:1": { "version": "stable" },
"ghcr.io/devcontainers/features/java:1": { "version": "21" },
// Container and orchestration tools
"ghcr.io/devcontainers/features/docker-in-docker:2": {},
"ghcr.io/devcontainers/features/docker-outside-of-docker:1": {},
"ghcr.io/devcontainers/features/kubectl-helm-minikube:1": {},
// Cloud CLIs
"ghcr.io/devcontainers/features/aws-cli:1": {},
"ghcr.io/devcontainers/features/azure-cli:1": {},
"ghcr.io/devcontainers/features/github-cli:1": {},
// Database clients
"ghcr.io/devcontainers/features/postgresql-client:1": {},
// Shell and utilities
"ghcr.io/devcontainers/features/common-utils:2": {
"installZsh": true,
"installOhMyZsh": true
},
"ghcr.io/devcontainers/features/sshd:1": {},
"ghcr.io/devcontainers/features/git-lfs:1": {}
}
}Docker Compose 多服务设置
对于需要数据库和缓存的应用,Dev Containers 与 Docker Compose 集成。在 docker-compose.yml 中定义服务并从 devcontainer.json 引用。
The key pattern is to use sleep infinity as the command for the main development service. This keeps the container running so VS Code can attach to it. The actual development server is started by the developer or by postStartCommand, not by Docker Compose directly. Other services like databases run their normal entrypoints.
# .devcontainer/docker-compose.yml
services:
app:
build:
context: ..
dockerfile: .devcontainer/Dockerfile
volumes:
- ..:/workspace:cached
- node-modules:/workspace/node_modules
command: sleep infinity
ports:
- "3000:3000"
- "9229:9229" # Node.js debugger
environment:
DATABASE_URL: postgresql://postgres:postgres@db:5432/myapp
REDIS_URL: redis://redis:6379
NODE_ENV: development
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: myapp
volumes:
- postgres-data:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis-data:/data
volumes:
node-modules:
postgres-data:
redis-data:// devcontainer.json with Docker Compose
{
"name": "Full Stack Dev",
"dockerComposeFile": "docker-compose.yml",
"service": "app",
"workspaceFolder": "/workspace",
"forwardPorts": [3000, 5432, 6379],
"postCreateCommand": "npm install && npx prisma migrate dev --name init",
"customizations": { "vscode": {
"extensions": ["prisma.prisma", "dbaeumer.vscode-eslint"]
}}
}端口转发和网络
开发容器自动将端口从容器转发到主机。在 devcontainer.json 中配置转发行为。
{
"forwardPorts": [3000, 5432, 6379, 8080],
"portsAttributes": {
"3000": { "label": "Frontend", "onAutoForward": "openBrowser" },
"5432": { "label": "PostgreSQL", "onAutoForward": "silent" },
"6379": { "label": "Redis", "onAutoForward": "ignore" },
"8080": { "label": "API", "onAutoForward": "notify", "requireLocalPort": true }
},
"otherPortsAttributes": { "onAutoForward": "silent" }
}环境变量和密钥
支持多种注入环境变量的方式:devcontainer.json 内联、.env 文件、或 GitHub Codespaces 密钥。
// Method 1: Inline
{ "containerEnv": { "NODE_ENV": "development", "LOG_LEVEL": "debug" },
"remoteEnv": { "LOCAL_USER": "\${localEnv:USER}" } }
// Method 2: .env file (add to .gitignore!)
// { "runArgs": ["--env-file", ".devcontainer/.env"] }
// .devcontainer/.env:
// DATABASE_URL=postgresql://user:pass@db:5432/myapp
// AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
// Method 3: GitHub Codespaces secrets
// GitHub > Settings > Codespaces > Secrets
// Available as env vars, never committedVS Code 扩展和设置
指定容器内安装的扩展和编辑器设置,确保每个开发者有相同的工具配置。
Extensions listed in the customizations block are installed inside the container, not on the host VS Code. This distinction matters because some extensions need access to language servers, runtimes, or tools that only exist inside the container. Extensions like ESLint need Node.js, Python extensions need the Python interpreter, and database extensions need database clients. By installing them in the container, they automatically have access to everything they need.
// VS Code customizations in devcontainer.json
{
"customizations": {
"vscode": {
"extensions": [
// Linting and formatting
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"stylelint.vscode-stylelint",
// Language support
"ms-python.python",
"golang.go",
"rust-lang.rust-analyzer",
// Database and API tools
"prisma.prisma",
"humao.rest-client",
// Git and collaboration
"eamodio.gitlens",
"github.copilot",
// Testing
"vitest.explorer"
],
"settings": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.tabSize": 2,
"editor.rulers": [80, 120],
"typescript.preferences.importModuleSpecifier": "relative",
"files.trimTrailingWhitespace": true,
"files.insertFinalNewline": true
}
}
}
}Post-Create 和 Post-Start 命令
生命周期命令在容器设置的特定时间点运行,自动化依赖安装和服务启动。
Understanding the lifecycle order is critical for efficient container setup. Commands that should only run once (like initial dependency installation) belong in postCreateCommand, while commands that should run on every restart (like database migrations) belong in postStartCommand. The object syntax allows running multiple commands in parallel, which speeds up container initialization significantly.
{
// Runs once after the container is first created
"postCreateCommand": "npm install && npx prisma generate",
// Runs every time the container starts
"postStartCommand": "npm run db:migrate",
// Runs every time VS Code attaches to the container
"postAttachCommand": "git fetch --all",
// Runs on rebuild to update dependencies incrementally
"updateContentCommand": "npm install",
// Parallel commands (object syntax — runs simultaneously):
"postCreateCommand": {
"deps": "npm install",
"db": "npx prisma migrate dev",
"seed": "npx prisma db seed",
"codegen": "npm run codegen"
},
// Runs on HOST before the container is built
"initializeCommand": "echo Starting dev container setup..."
}
// Complete lifecycle order:
// 1. initializeCommand — runs on HOST before build
// 2. onCreateCommand — once when container is created
// 3. updateContentCommand — on create and rebuild
// 4. postCreateCommand — once after container is created
// 5. postStartCommand — every time container starts
// 6. postAttachCommand — every time editor attaches卷和挂载持久化
工作区默认绑定挂载。可为缓存和数据添加持久化挂载。
{
"mounts": [
"source=myproject-node-modules,target=/workspace/node_modules,type=volume",
"source=\${localEnv:HOME}/.ssh,target=/home/node/.ssh,type=bind,readonly",
"source=\${localEnv:HOME}/.gitconfig,target=/home/node/.gitconfig,type=bind,readonly",
"source=\${localEnv:HOME}/.aws,target=/home/node/.aws,type=bind,readonly",
"target=/tmp,type=tmpfs"
],
"workspaceMount": "source=\${localWorkspaceFolder},target=/workspace,type=bind,consistency=cached",
"workspaceFolder": "/workspace"
}GPU 支持 ML/AI 开发
支持 GPU 直通。在主机安装 NVIDIA Container Toolkit 后,可将 GPU 暴露给容器。
GPU support is particularly valuable for teams working on machine learning models, computer vision, natural language processing, or any CUDA-accelerated workload. The hostRequirements field with gpu set to optional allows the same devcontainer.json to work on both GPU and non-GPU machines, making it versatile across team members with different hardware.
// GPU-enabled dev container for ML/AI development
{
"image": "mcr.microsoft.com/devcontainers/python:3.12",
"features": {
"ghcr.io/devcontainers/features/nvidia-cuda:1": {
"installCudnn": true,
"cudaVersion": "12.4",
"cudnnVersion": "9"
},
"ghcr.io/devcontainers/features/python:1": { "version": "3.12" }
},
"runArgs": [
"--gpus", "all" // Pass all GPUs to container
// "--gpus", "device=0" // Or pass a specific GPU
],
"hostRequirements": {
"gpu": "optional" // Works without GPU too
},
"postCreateCommand": "pip install torch torchvision transformers datasets",
"customizations": {
"vscode": {
"extensions": [
"ms-python.python",
"ms-toolsai.jupyter",
"ms-toolsai.vscode-jupyter-slideshow"
]
}
}
}
// Host prerequisites:
// 1. NVIDIA driver installed on the host machine
// 2. Install NVIDIA Container Toolkit:
// sudo apt install nvidia-container-toolkit
// sudo systemctl restart docker
// 3. Verify setup:
// docker run --gpus all nvidia/cuda:12.4-base nvidia-smi多根工作区
支持在单个 VS Code 窗口中打开多个仓库,适用于微服务架构。
{
"name": "Microservices Dev",
"dockerComposeFile": "docker-compose.yml",
"service": "workspace",
"workspaceFolder": "/workspaces",
"postCreateCommand": {
"frontend": "cd /workspaces && git clone https://github.com/org/frontend.git",
"backend": "cd /workspaces && git clone https://github.com/org/backend-api.git"
}
}
// Or use workspace file .devcontainer/workspace.code-workspace:
// { "folders": [
// { "path": "/workspaces/frontend", "name": "Frontend" },
// { "path": "/workspaces/backend-api", "name": "Backend" }
// ]}Dev Container 模板和社区 Features
规范包含模板系统,为常见场景提供入门配置,可从官方和社区仓库获取。
# Install devcontainer CLI
npm install -g @devcontainers/cli
# Apply a template:
devcontainer templates apply \
--template-id ghcr.io/devcontainers/templates/typescript-node
# Or via VS Code: Dev Containers: Add Dev Container Configuration Files...
# Community Features (add to "features" in devcontainer.json):
# ghcr.io/devcontainers-contrib/features/bun:1
# ghcr.io/devcontainers-contrib/features/pnpm:2
# ghcr.io/devcontainers-contrib/features/turbo-cli:1
# ghcr.io/devcontainers-contrib/features/act:1 (GitHub Actions local)
# ghcr.io/devcontainers-contrib/features/mkcert:1 (local HTTPS)JetBrains Dev Container 支持
JetBrains IDE 通过远程开发网关支持 Dev Containers,读取 devcontainer.json 并通过 SSH 连接。
{
"customizations": {
"jetbrains": {
"backend": {
"productCode": "IU", // IntelliJ IDEA Ultimate
// "PS" PhpStorm, "WS" WebStorm, "PY" PyCharm, "GO" GoLand, "CL" CLion
"plugins": ["org.jetbrains.plugins.go", "com.intellij.database"]
}
},
"vscode": { "extensions": ["dbaeumer.vscode-eslint"] }
}
}
// Steps: Install JetBrains Gateway > Select "Dev Containers"
// > Choose project > Gateway builds container and connects IDE性能优化
配置不当时开发容器可能很慢,尤其在 macOS 上。以下是最有效的优化。
- 对 node_modules 等使用命名卷而非绑定挂载
- 启用 Docker BuildKit 加速构建
- 使用预构建镜像而非每次从 Dockerfile 构建
- 配置 Codespaces 预构建
- 从主机挂载 .gitconfig 和 SSH 密钥
- 设置 updateContentCommand 增量更新依赖
- 使用 cacheFrom 利用注册表层缓存
// Performance-optimized devcontainer.json
{
"image": "mcr.microsoft.com/devcontainers/typescript-node:20",
"mounts": ["source=proj-nm,target=/workspace/node_modules,type=volume"],
"workspaceMount": "source=\${localWorkspaceFolder},target=/workspace,type=bind,consistency=cached",
"workspaceFolder": "/workspace",
"cacheFrom": "ghcr.io/myorg/devcontainer-cache:latest",
"updateContentCommand": "npm install",
"runArgs": ["--memory=8g", "--cpus=4"],
"hostRequirements": { "cpus": 4, "memory": "8gb", "storage": "32gb" }
}团队入职与 Dev Containers
开发容器将入职从数天变成一键操作。结合 GitHub Codespaces,零本地设置。
The traditional onboarding process involves installing the correct versions of multiple language runtimes, setting up databases, configuring environment variables, installing editor plugins, and troubleshooting platform-specific issues. With Dev Containers, all of this is encoded in the repository. The onboarding documentation reduces from pages of instructions to a single step: open the project in VS Code and accept the container prompt.
# Option A: Local development (VS Code)
# 1. Install Docker Desktop and VS Code
# 2. Install Dev Containers extension
# 3. Clone the repository and open in VS Code:
git clone https://github.com/myorg/myproject.git
code myproject
# 4. Click "Reopen in Container" when prompted
# 5. Done — full environment ready in 2-5 minutes
# Option B: Cloud development (GitHub Codespaces)
# 1. Go to github.com/myorg/myproject
# 2. Click Code > Codespaces > Create codespace
# 3. Done — browser-based VS Code, zero local install needed
# What devcontainer.json provides automatically:
# - Correct Node.js / Python / Go / Rust version
# - All required VS Code extensions pre-installed
# - Database (PostgreSQL) running and seeded
# - Redis cache running
# - Environment variables configured
# - Git hooks and linters configured
# - All dependencies installed (npm/pip/cargo)
# - Ports forwarded for local testing
# - Shared editor settings (formatting, tab size, rulers)CI/CD 与 Dev Containers
devcontainer CLI 和 GitHub Actions 让你在与开发者本地相同的环境中构建和测试。
The devcontainers/ci GitHub Action handles building the dev container image, starting the container, running your commands inside it, and optionally pushing the built image to a container registry for caching. This means your CI pipeline uses the exact same Node.js version, Python packages, system libraries, and tooling that developers use locally. No more debugging CI-only failures caused by environment differences.
# .github/workflows/ci.yml — Dev Container CI/CD
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build and run dev container
uses: devcontainers/ci@v0.3
with:
# Run all checks inside the dev container
runCmd: |
npm run lint
npm run type-check
npm run test
npm run build
# Cache the built image in a container registry
imageName: ghcr.io/myorg/devcontainer-cache
cacheFrom: ghcr.io/myorg/devcontainer-cache
push: filter
refFilterForPush: refs/heads/main
# Standalone CLI usage (local or any CI system):
# npm install -g @devcontainers/cli
# devcontainer build --workspace-folder .
# devcontainer up --workspace-folder .
# devcontainer exec --workspace-folder . npm test
# devcontainer exec --workspace-folder . npm run build安全最佳实践
开发容器运行任意代码,安全很重要。遵循以下实践。
- 不要以 root 运行——使用 remoteUser
- 用 SHA 摘要固定镜像版本
- 密钥存储在 Codespaces 密钥中,不要放在 devcontainer.json
- 审计第三方 Features
- 使用 Docker Content Trust 验证签名
- 避免 --privileged
- 定期重建更新基础镜像
- .env 文件加入 .gitignore
常见语言模式
2026 年最流行语言的生产级 devcontainer.json 示例。
Node.js / TypeScript
{
"image": "mcr.microsoft.com/devcontainers/typescript-node:20",
"features": { "ghcr.io/devcontainers-contrib/features/pnpm:2": {} },
"forwardPorts": [3000, 5173],
"postCreateCommand": "pnpm install",
"mounts": ["source=nm,target=/workspace/node_modules,type=volume"],
"customizations": { "vscode": {
"extensions": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode"]
}}
}Python
{
"image": "mcr.microsoft.com/devcontainers/python:3.12",
"forwardPorts": [8000],
"postCreateCommand": "pip install -r requirements.txt",
"customizations": { "vscode": {
"extensions": ["ms-python.python", "charliermarsh.ruff"],
"settings": { "python.defaultInterpreterPath": "/usr/local/bin/python" }
}}
}Go
{
"image": "mcr.microsoft.com/devcontainers/go:1.22",
"features": { "ghcr.io/devcontainers/features/docker-in-docker:2": {} },
"forwardPorts": [8080],
"postCreateCommand": "go mod download",
"mounts": ["source=gomod,target=/go/pkg/mod,type=volume"],
"customizations": { "vscode": { "extensions": ["golang.go"] }}
}Rust
{
"image": "mcr.microsoft.com/devcontainers/rust:1",
"forwardPorts": [8080],
"postCreateCommand": "cargo build",
"mounts": [
"source=cargo-reg,target=/usr/local/cargo/registry,type=volume",
"source=cargo-target,target=/workspace/target,type=volume"
],
"customizations": { "vscode": {
"extensions": ["rust-lang.rust-analyzer", "vadimcn.vscode-lldb"],
"settings": { "rust-analyzer.checkOnSave.command": "clippy" }
}}
}Java
{
"image": "mcr.microsoft.com/devcontainers/java:21",
"features": { "ghcr.io/devcontainers/features/java:1": {
"version": "21", "installMaven": true, "installGradle": true } },
"forwardPorts": [8080, 5005],
"postCreateCommand": "./mvnw dependency:resolve",
"mounts": ["source=m2,target=/home/vscode/.m2/repository,type=volume"],
"customizations": { "vscode": {
"extensions": ["vscjava.vscode-java-pack", "vmware.vscode-spring-boot"]
}}
}故障排查指南
最常见的 Dev Container 问题及解决方案。
| Issue | Cause | Solution |
|---|---|---|
| Container fails to build | Dockerfile error or missing image | Check Container Log via Command Palette. Verify image name. |
| Slow file I/O on macOS | Bind mounts through Linux VM | Use named volumes for node_modules. Set consistency: cached. |
| Port already in use | Host port conflict | Stop conflicting service or change port in devcontainer.json. |
| Extensions not installing | Platform/architecture mismatch | Check extension supports Linux containers. |
| Git SSH auth fails | SSH agent not forwarded | Run ssh-add on host. VS Code forwards agent automatically. |
| Out of disk space | Docker images and cache | Run docker system prune. Increase Docker disk allocation. |
| Features fail to install | Network issues or version conflict | Check connectivity. Pin Feature versions. |
| Container keeps restarting | postStartCommand exits with error | Check terminal output. Use background execution for long commands. |
# Common troubleshooting commands:
# View dev container build logs
# VS Code: Command Palette > Dev Containers: Show Container Log
# List running dev containers
docker ps --filter "label=devcontainer.local_folder"
# Inspect container configuration
docker inspect <container-id> | jq ".[0].Config"
# Check Docker resource usage
docker system df
# Clean up unused images, containers, and volumes
docker system prune -a --volumes
# Force rebuild without cache
# VS Code: Command Palette > Dev Containers: Rebuild Without Cache
# Test devcontainer.json validity with CLI:
npm install -g @devcontainers/cli
devcontainer build --workspace-folder .
devcontainer up --workspace-folder .
# Check container logs for errors:
docker logs <container-id> --tail 100
# Enter the container manually for debugging:
docker exec -it <container-id> /bin/bash常见问题
Dev Containers 和 Docker Compose 有什么区别?
Docker Compose 定义多容器栈,Dev Containers 定义开发环境(包含编辑器设置和扩展)。Dev Containers 可在底层使用 Docker Compose。
不用 VS Code 能用 Dev Containers 吗?
可以。JetBrains IDE 原生支持 devcontainer.json。devcontainer CLI 可从任何终端使用。DevPod 和 Codespaces 也支持。
Dev Containers 影响性能吗?
首次构建需几分钟。后续启动因 Docker 缓存而很快。macOS 上对依赖目录使用命名卷可消除文件系统瓶颈。
可以在 monorepo 中使用吗?
可以。将 devcontainer.json 放在仓库根目录。多仓库项目用 Docker Compose 定义所有服务。
如何共享 SSH 密钥和 Git 配置?
VS Code 自动转发本地 SSH 代理。Git 凭据通过内置助手转发。额外凭据可用挂载或环境变量。
Dev Containers 免费吗?
规范、VS Code 和扩展免费。本地容器无额外费用。Codespaces 有免费层(120 核心小时/月)。
能访问主机文件系统吗?
工作区默认挂载。可在 devcontainer.json 中添加额外挂载。端口自动转发。
修改配置后如何更新?
在 VS Code 中运行 Rebuild Container。需要全新构建用 Rebuild Without Cache。Codespaces 中从命令面板重建。
总结
Dev Containers 是 2026 年可复现开发环境最实用的方案。通过将开发设置定义为 devcontainer.json 提交到仓库,确保每个团队成员和 CI 流水线运行相同环境。从预构建镜像开始,添加 Features,逐步迭代。
Getting Started Checklist
- Install Docker Desktop and VS Code with the Dev Containers extension
- Create a .devcontainer folder in your repository root
- Add a devcontainer.json with a pre-built image matching your language
- Add Features for additional tools (Docker-in-Docker, AWS CLI, database clients)
- Configure VS Code extensions and settings in the customizations block
- Set up lifecycle commands for dependency installation and service startup
- Add Docker Compose if you need databases or other services
- Use named volumes for dependency directories to improve macOS performance
- Configure GitHub Codespaces prebuilds for instant cloud environments
- Set up CI/CD with the devcontainer CLI or GitHub Actions integration
For additional resources, visit the official Dev Container specification at containers.dev, explore the pre-built images and Features at github.com/devcontainers, and check the VS Code remote development documentation. The ecosystem is growing rapidly with community Features and Templates covering nearly every development scenario.