writing-skills
writing-skills
Use when creating new skills, editing existing skills, or verifying skills work before deployment
skill-148Expert guidance for Development Containers (devcontainers) in VS Code. Create, configure, and manage devcontainer.json files, use Templates and Features, integrate with Docker/Docker Compose, and troubleshoot common issues. Use when working with devcontainers, containerized development environments, or when user mentions devcontainer.json, dev containers, V…
Independent GitHub snapshot · Automated classification · Original documentation governs
Expert guidance for working with Development Containers (devcontainers) - a standardized way to create fully-featured, containerized development environments.
Activate this skill when:
A development container (dev container) is a running Docker container with a well-defined tool/runtime stack and its prerequisites. The configuration is defined in a devcontainer.json file that tells VS Code (or other supporting tools) how to access or create a development container.
Key Benefits:
The Specification: Dev containers follow the open Development Containers Specification maintained by the devcontainers community.
Docker
VS Code
ms-vscode-remote.remote-containers)System Resources
Windows/macOS:
Linux:
sudo usermod -aG docker $USERThe devcontainer.json file is the core configuration for your dev container. It can be placed in one of two locations:
.devcontainer/devcontainer.json (recommended for complex setups).devcontainer.json (root of project)The easiest way to create a dev container is using a pre-built Template:
F1 or Cmd/Ctrl+Shift+PDev Containers: Add Dev Container Configuration Files...Dev Containers: Reopen in ContainerVS Code will build the container and reopen your workspace inside it.
Minimal Example (Using Pre-built Image):
{
"name": "My Project",
"image": "mcr.microsoft.com/devcontainers/typescript-node:20",
"forwardPorts": [3000],
"customizations": {
"vscode": {
"extensions": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
]
}
}
}
Using a Dockerfile:
{
"name": "My Custom Container",
"build": {
"dockerfile": "Dockerfile",
"context": "..",
"args": {
"VARIANT": "18"
}
},
"forwardPorts": [3000, 5000],
"postCreateCommand": "npm install",
"customizations": {
"vscode": {
"settings": {
"terminal.integrated.defaultProfile.linux": "bash"
},
"extensions": ["dbaeumer.vscode-eslint"]
}
}
}
Using Docker Compose:
{
"name": "My Multi-Container App",
"dockerComposeFile": "docker-compose.yml",
"service": "app",
"workspaceFolder": "/workspace",
"forwardPorts": [3000],
"postCreateCommand": "npm install",
"customizations": {
"vscode": {
"extensions": ["dbaeumer.vscode-eslint"]
}
}
}
For quick starts, this skill includes practical, copy-paste devcontainer.json templates in assets/templates/:
Each template is fully commented and demonstrates different patterns. For detailed template descriptions, selection guidance, and usage instructions, see references/TEMPLATES_GUIDE.md.
Container Definition:
name: Display name for the containerimage: Pre-built Docker image to usebuild: Build configuration (dockerfile, context, args, target, cacheFrom, options)dockerComposeFile: Path to docker-compose.yml fileservice: Docker Compose service name to connect toEnvironment Setup:
workspaceFolder: Path where workspace is mounted (default: /workspaces/<project-name>)workspaceMount: Custom workspace mount configurationmounts: Additional volume/bind mountscontainerEnv: Environment variables for the containercontainerUser: User for starting the container (default: image default)remoteUser: User to run as inside container (default: root or image default)remoteEnv: Environment variables for remote processes and IDE serverupdateRemoteUserUID: Update container user's UID/GID to match local user (Linux only)Port Forwarding:
forwardPorts: Array of ports to forward (e.g., [3000, 8080])appPort: Application ports exposed by container (deprecated in favor of forwardPorts)portsAttributes: Configure port labels, protocols, auto-forward behavior, and elevationotherPortsAttributes: Default properties for ports not explicitly configuredLifecycle Scripts:
initializeCommand: Runs locally before anything elseonCreateCommand: Runs once when container is createdupdateContentCommand: Runs when container config changespostCreateCommand: Runs after container creation (often used for npm install, pip install)postStartCommand: Runs every time the container startspostAttachCommand: Runs every time you attach to the containerwaitFor: Which command to wait for before starting UI (default: updateContentCommand)Advanced Container Options:
runArgs: Additional Docker run argumentsinit: Pass --init flag for proper signal handlingprivileged: Run container in privileged modecapAdd: Docker capabilities to addsecurityOpt: Docker security optionsoverrideCommand: Override the default command from the imageshutdownAction: Action when disconnecting (none or stopContainer/stopCompose)Features and Environment:
features: Features to add to the containeroverrideFeatureInstallOrder: Control the order Features are installeduserEnvProbe: How to load user environment (none, loginShell, loginInteractiveShell, interactiveShell)Host Requirements:
hostRequirements: Minimum host hardware (cpus, memory, storage, gpu)Security and Secrets:
secrets: Recommended secrets with descriptions and documentation URLsVS Code Customization:
customizations.vscode.extensions: Extensions to install in the containercustomizations.vscode.settings: VS Code settings for the containercustomizations: Tool-specific customizations for other editors/toolsFeatures are self-contained, shareable units of installation code that add tools, runtimes, or libraries to your container.
Method 1: During Setup
When running Dev Containers: Add Dev Container Configuration Files..., you'll be prompted to select Features.
Method 2: Add to Existing Config
F1Dev Containers: Configure Container FeaturesMethod 3: Edit devcontainer.json Directly
{
"name": "My Project",
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
"features": {
"ghcr.io/devcontainers/features/node:1": {
"version": "20"
},
"ghcr.io/devcontainers/features/git:1": {
"version": "latest"
},
"ghcr.io/devcontainers/features/github-cli:1": {},
"ghcr.io/devcontainers/features/docker-in-docker:2": {
"version": "latest",
"moby": true
}
}
}
Browse all at https://containers.dev/features:
Features follow semantic versioning. You can pin to specific versions:
"features": {
"ghcr.io/devcontainers/features/node:1": {}, // Latest v1.x.x
"ghcr.io/devcontainers/features/python:1.0": {}, // Latest v1.0.x
"ghcr.io/devcontainers/features/go:1.0.0": {} // Exact version 1.0.0
}
You can create your own Features using the feature-starter template. Each Feature is a folder with:
devcontainer-feature.json - Metadata and optionsinstall.sh - Installation scriptBy default, Features are installed in an implementation-defined order. To control this:
{
"features": {
"ghcr.io/devcontainers/features/common-utils:1": {},
"ghcr.io/devcontainers/features/node:1": {},
"ghcr.io/devcontainers/features/docker-in-docker:2": {}
},
"overrideFeatureInstallOrder": [
"ghcr.io/devcontainers/features/common-utils",
"ghcr.io/devcontainers/features/node",
"ghcr.io/devcontainers/features/docker-in-docker"
]
}
For comprehensive documentation of all devcontainer.json properties with detailed examples, see references/JSON_SCHEMA_REFERENCE.md.
This reference covers:
Open Local Project in Container:
Dev Containers: Reopen in Container (F1)Clone Repository in Container Volume (better performance on Windows/macOS):
Dev Containers: Clone Repository in Container Volume...Open GitHub PR:
Dev Containers: Clone Repository in Container Volume...Rebuild Container (after config changes):
Dev Containers: Rebuild ContainerDev Containers: Rebuild Container Without Cache (full rebuild)Attach to Running Container:
Dev Containers: Attach to Running Container...Important Limitation: Multi-root workspaces (.code-workspace files) open all folders in the same container. To use different containers per package, open each folder separately.
Pattern 1: Separate Package Containers (different tech stacks)
monorepo/
├── apps/
│ ├── frontend/.devcontainer/devcontainer.json
│ └── backend/.devcontainer/devcontainer.json
Frontend (.devcontainer/devcontainer.json):
{
"name": "Frontend",
"image": "mcr.microsoft.com/devcontainers/typescript-node:20",
"workspaceFolder": "/workspaces/monorepo/apps/frontend",
"workspaceMount": "source=${localWorkspaceFolder}/../..,target=/workspaces/monorepo,type=bind"
}
Workflow:
frontend/ → "Open Folder in Container"Pattern 2: Unified Polyglot Container (all tools in one)
{
"name": "Monorepo All",
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
"features": {
"ghcr.io/devcontainers/features/node:1": {"version": "20"},
"ghcr.io/devcontainers/features/python:1": {"version": "3.11"},
"ghcr.io/devcontainers/features/go:1": {}
}
}
Pattern 3: Docker Compose Multi-Container (services in separate containers)
Use Docker Compose when packages need to run simultaneously (frontend + backend + db):
services:
frontend:
build: ./apps/frontend
volumes: [".:/workspace:cached"]
backend:
build: ./apps/backend
volumes: [".:/workspace:cached"]
db:
image: postgres:14
{
"name": "Monorepo",
"dockerComposeFile": "docker-compose.yml",
"service": "frontend",
"workspaceFolder": "/workspace"
}
Choose "frontend" or "backend" as primary service. Access other containers via docker exec or attach in separate windows.
For in-depth coverage of advanced scenarios, see the references/ directory:
docker-compose.yml:
services:
app:
build: .
volumes:
- .:/workspace:cached
command: sleep infinity
db:
image: postgres:14
environment:
POSTGRES_PASSWORD: example
devcontainer.json:
{
"name": "App with Database",
"dockerComposeFile": "docker-compose.yml",
"service": "app",
"workspaceFolder": "/workspace",
"postCreateCommand": "npm install"
}
{
"image": "mcr.microsoft.com/devcontainers/typescript-node:20",
"remoteUser": "node"
}
{
"image": "mcr.microsoft.com/devcontainers/python:3.11",
"mounts": [
"source=${localEnv:HOME}/.ssh,target=/home/node/.ssh,readonly,type=bind"
],
"containerEnv": {
"DATABASE_URL": "postgresql://localhost/mydb"
}
}
For comprehensive debugging guides, see references/RECOVERY_DEBUGGING.md.
Common Issues:
docker ps works. On Linux: sudo systemctl status dockerlsof -i :<port> (macOS/Linux) or netstat -ano | findstr :<port> (Windows)Dev Containers: Reopen in Recovery Container to debug. See RECOVERY_DEBUGGING.mdremoteUser or see SECURITY.md for non-root configuration.devcontainer/ so all developers use the same environmentmcr.microsoft.com/devcontainers/ for reliabilityPre-building images improves startup time and enables CI/CD integration. See references/PREBUILDING.md for comprehensive guides.
Quick Example (GitHub Actions):
name: CI
on: [push]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: devcontainers/ci@v0.3
with:
imageName: ghcr.io/${{ github.repository }}-devcontainer
cacheFrom: ghcr.io/${{ github.repository }}-devcontainer
push: always
runCmd: npm test
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VS Code Commands (open with F1 or Cmd/Ctrl+Shift+P):
Dev Containers: Reopen in ContainerDev Containers: Rebuild ContainerDev Containers: Add Dev Container Configuration Files...Dev Containers: Configure Container FeaturesDev Containers: Clone Repository in Container Volume...Dev Containers: Attach to Running Container...Dev Containers: Show Container LogKey Configuration Locations:
.devcontainer/devcontainer.json (recommended).devcontainer.json (alternative).devcontainer/Dockerfile.devcontainer/docker-compose.yml