Advanced DevContainers
Master advanced DevContainer configurations, multi-container setups, performance optimization, and enterprise patterns.
DevContainer Features
Modular, reusable configuration components
What are Features?
Features are self-contained units of installation code and configuration. They allow you to quickly add tools, runtimes, or libraries to any DevContainer without modifying the base image.
- Composable - mix and match features
- Versioned - pin to specific versions
- Shareable - publish your own
- Configurable - pass options
{
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
"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": {},
"ghcr.io/devcontainers/features/kubectl-helm-minikube:1": {}
}
}
Popular DevContainer Features
Node.js
ghcr.io/devcontainers/features/node
Python
ghcr.io/devcontainers/features/python
Go
ghcr.io/devcontainers/features/go
Rust
ghcr.io/devcontainers/features/rust
Docker-in-Docker
ghcr.io/devcontainers/features/docker-in-docker
Kubectl & Helm
ghcr.io/devcontainers/features/kubectl-helm-minikube
AWS CLI
ghcr.io/devcontainers/features/aws-cli
GitHub CLI
ghcr.io/devcontainers/features/github-cli
Multi-Container Setups
Docker Compose for complex development environments
Full-Stack Application Example
version: '3.8'
services:
app:
build:
context: .
dockerfile: .devcontainer/Dockerfile
volumes:
- ..:/workspace:cached
- node_modules:/workspace/node_modules
command: sleep infinity
networks:
- dev-network
depends_on:
- db
- redis
- elasticsearch
db:
image: postgres:16
restart: unless-stopped
volumes:
- postgres-data:/var/lib/postgresql/data
environment:
POSTGRES_USER: dev
POSTGRES_PASSWORD: dev
POSTGRES_DB: myapp_dev
networks:
- dev-network
redis:
image: redis:7-alpine
restart: unless-stopped
networks:
- dev-network
elasticsearch:
image: elasticsearch:8.11.0
environment:
- discovery.type=single-node
- xpack.security.enabled=false
volumes:
- es-data:/usr/share/elasticsearch/data
networks:
- dev-network
volumes:
postgres-data:
es-data:
node_modules:
networks:
dev-network:
{
"name": "Full Stack Dev",
"dockerComposeFile": "docker-compose.yml",
"service": "app",
"workspaceFolder": "/workspace",
"features": {
"ghcr.io/devcontainers/features/node:1": {},
"ghcr.io/devcontainers/features/python:1": {}
},
"forwardPorts": [3000, 5432, 6379, 9200],
"customizations": {
"vscode": {
"extensions": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"ckolkman.vscode-postgres",
"redis.redis-for-vscode"
],
"settings": {
"editor.formatOnSave": true
}
}
},
"postCreateCommand": "npm install",
"remoteEnv": {
"DATABASE_URL": "postgres://dev:dev@db:5432/myapp_dev",
"REDIS_URL": "redis://redis:6379",
"ELASTICSEARCH_URL": "http://elasticsearch:9200"
}
}
Service Communication
DNS Resolution
Services are reachable by their name: db, redis
Port Mapping
Use forwardPorts to access from your local browser
Environment Variables
Use remoteEnv to inject connection strings
Performance Optimization
Maximize DevContainer build speed and runtime performance
Build Optimization
Layer Caching
# Bad: Invalidates cache frequently
COPY . .
RUN npm install
# Good: Leverage layer caching
COPY package*.json ./
RUN npm ci
COPY . .
Multi-Stage Builds
# Build stage with all dev tools
FROM node:20 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Dev container inherits from builder
FROM builder AS devcontainer
RUN npm install -g typescript@latest
Prebuilds
Build images in CI and push to registry for instant startup:
{
"image": "ghcr.io/myorg/devcontainer-node:latest",
"cacheFrom": "ghcr.io/myorg/devcontainer-node"
}
Runtime Performance
Volume Mounts
# Use named volumes for node_modules
volumes:
- ..:/workspace:cached
- node_modules:/workspace/node_modules
# Use :cached for better macOS performance
# Use :delegated for write-heavy workloads
Resource Limits
{
"hostRequirements": {
"cpus": 4,
"memory": "8gb",
"storage": "32gb"
},
"runArgs": [
"--cpus=4",
"--memory=8g"
]
}
Parallelization
{
"postCreateCommand": "npm ci & pip install -r requirements.txt & wait",
"initializeCommand": ["./scripts/setup.sh"]
}
Faster with prebuilds
Mount flag for macOS
For node_modules
Exclude unnecessary files
Enterprise Patterns
Scalable DevContainer strategies for large organizations
Base Image Strategy
Base Layer
Company-wide security tools, certificates, proxies
ghcr.io/myorg/base:latest
Language Layer
Node, Python, Java with standard versions
ghcr.io/myorg/node-20:latest
Project Layer
Project-specific tools and configs
devcontainer.json in repo
Private Registry Authentication
{
"image": "ghcr.io/myorg/private-devcontainer:latest",
// For GitHub Container Registry
"containerEnv": {
"GITHUB_TOKEN": "${localEnv:GITHUB_TOKEN}"
},
// For AWS ECR
"initializeCommand": "aws ecr get-login-password | docker login --username AWS --password-stdin 123456789.dkr.ecr.us-east-1.amazonaws.com",
// For Azure Container Registry
"initializeCommand": "az acr login --name myregistry",
// Using Docker credential helpers
"runArgs": [
"-v", "${localEnv:HOME}/.docker/config.json:/root/.docker/config.json:ro"
]
}
Template Repository Structure
devcontainer-templates/
+-- .github/
| +-- workflows/
| +-- build-push.yml # CI to build/push images
+-- base/
| +-- Dockerfile
| +-- devcontainer.json
+-- node-20/
| +-- Dockerfile
| +-- devcontainer.json
+-- python-312/
| +-- Dockerfile
| +-- devcontainer.json
+-- java-21/
| +-- Dockerfile
| +-- devcontainer.json
+-- full-stack/
| +-- Dockerfile
| +-- docker-compose.yml
| +-- devcontainer.json
+-- ml-gpu/
+-- Dockerfile
+-- devcontainer.json
Best Practices
- Version images with semantic versioning
- Automated builds on push to main
- Security scanning in CI pipeline
- Documentation for each template
- Changelog for breaking changes
- Test containers before release
Lifecycle Scripts
Execute scripts at different container lifecycle stages
| Hook | When | Use Case |
|---|---|---|
| initializeCommand | Before container created (on host) | Docker login, pull base images |
| onCreateCommand | After container created (first time only) | Install dependencies, build projects |
| updateContentCommand | After source updates (prebuilds) | Incremental dependency updates |
| postCreateCommand | After onCreate/updateContent | Final setup, start services |
| postStartCommand | Every container start | Start dev servers, background jobs |
| postAttachCommand | Every attach to container | Shell customization, greetings |
Example Configuration
{
"initializeCommand": "docker login ghcr.io",
"onCreateCommand": "npm ci && npm run build",
"updateContentCommand": "npm ci",
"postCreateCommand": ".devcontainer/setup.sh",
"postStartCommand": "npm run dev &",
"postAttachCommand": "echo 'Welcome! Run npm test to start.'"
}