| name | devcontainer |
| description | Create, update, and maintain robust devcontainer.json configurations and lifecycle scripts for reproducible development environments. |
| license | MIT |
Devcontainer
Create, update, and maintain robust devcontainer.json configurations and associated lifecycle scripts (e.g., onCreateCommand, updateContentCommand, postCreateCommand) to ensure reproducible, feature-rich, and secure development environments.
Core Process
- Locate or Create Configuration: Target
.devcontainer/devcontainer.json or .devcontainer/<name>/devcontainer.json.
- Define Base Metadata: Assign a descriptive
name and define the base image (e.g., mcr.microsoft.com/devcontainers/base:jammy).
- Configure Features: Leverage Dev Container Features (
ghcr.io/devcontainers/features/*) for modular tool installation instead of complex Dockerfiles.
- Define Lifecycle Scripts: Use
onCreateCommand, updateContentCommand, and postCreateCommand strategically based on execution timing.
- Customize IDE: Populate
customizations.vscode.extensions and customizations.vscode.settings for a ready-to-use editor experience.
Core Principles
- Features over Dockerfiles: Prefer standardized Dev Container features (e.g.,
ghcr.io/devcontainers/features/python:1) instead of custom RUN apt-get... in Dockerfiles for better caching and modularity.
- Lifecycle Script Separation:
onCreateCommand: Background OS-level updates, apt-get, or pipx installations (runs once when container is created).
updateContentCommand: Background OS-level or build-time setups that run after the workspace is mounted.
postCreateCommand: Installing project-level dependencies like npm install or pip install -r requirements.txt and foreground commands like pre-commit install (ensures full workspace availability; updateContentCommand can sometimes execute too early).
- Root vs RemoteUser: Execute system installs as
root (e.g., using sudo if remoteUser is vscode) and user installs (e.g., Python packages) as the remoteUser.
- Reproducibility: Pin feature versions and base image tags (e.g.,
:jammy instead of :latest).
When to Use
- When setting up a reproducible development environment for a repository.
- To standardize tooling, linters, and extensions for all contributors via VS Code or GitHub Codespaces.
- When upgrading base images or adding new Dev Container Features to an existing project.
When Not to Use
- For creating lightweight, production-ready Docker images (devcontainers are heavy and optimized for development, not production).
- If the project strictly uses Nix, Flox, or another purely declarative package manager without containerization.
- When executing a one-off script that doesn't require a persistent, isolated environment.
Common Pitfalls
- Monolithic Dockerfiles: Writing massive, custom
Dockerfiles full of apt-get commands instead of using standardized, cached Dev Container Features.
- Wrong Lifecycle Hook: Using
postCreateCommand for heavy OS-level installations, drastically delaying the time it takes for the user's workspace to become interactive.
- Root Permission Errors: Forgetting that certain
onCreateCommand scripts run as root, while postCreateCommand runs as the remoteUser (e.g., vscode), leading to permission denied errors on npm/pip installs.
Example: devcontainer.json
{
"name": "Dev Container (Python & Ansible)",
"customizations": {
"vscode": {
"extensions": [
"bierner.markdown-mermaid",
"DavidAnson.vscode-markdownlint",
"GitHub.copilot",
"GitHub.copilot-chat",
"GitHub.vscode-github-actions",
"ms-vscode.vscode-chat-customizations-evaluations",
"vscodevim.vim",
"vsls-contrib.codetour",
"xaver.clang-format"
],
"settings":
What to Avoid
- Monolithic Dockerfiles: Avoid massive custom Dockerfiles unless doing complex system setups unsupported by standard features.
- Using
latest Tags: Avoid ubuntu:latest or base images without explicit versions. Prefer stable tags like jammy.
- Long Synchronous Post-Create Commands: Move long-running OS package installs to
onCreateCommand or updateContentCommand to improve perceived startup time.
- Hardcoding Workspace Paths: Avoid hardcoding
/workspaces/.... Use the ${localWorkspaceFolder} or ${containerWorkspaceFolder} variables if needed.
Limitations
- Agents cannot natively build or attach to the devcontainer to test the environment interactively. Rely on schema validation, JSON linting, and best practices.
Related Skills
- yaml: You MUST load this skill when formatting or linting YAML configurations related to devcontainers.
- pre-commit: You MUST load this skill when configuring pre-commit hooks in the devcontainer.