Skip to main content
InfraGap.com Logo
Home
Getting Started
Core Concept What is a CDE? How It Works Benefits CDE Assessment Getting Started Guide
Implementation
Architecture Patterns DevContainers Language Quickstarts IDE Integration AI/ML Workloads Advanced DevContainers
Operations
Performance Optimization High Availability & DR Monitoring Capacity Planning Troubleshooting Runbooks
Security
Security Deep Dive Secrets Management Vulnerability Management Network Security IAM Guide Compliance Guide
Planning
Pilot Program Design Stakeholder Communication Risk Management Migration Guide Cost Analysis Vendor Evaluation Training Resources Team Structure Industry Guides
Resources
Tools Comparison CDE vs Alternatives Case Studies Lessons Learned Glossary FAQ

DevContainers Deep Dive

Complete guide to Development Containers - the specification that powers reproducible, containerized development environments

What are DevContainers?

Development Containers (DevContainers) are a standardized way to define complete development environments as code using Docker containers. The specification, maintained by the Development Containers Spec, allows developers to define their entire development environment - tools, runtimes, extensions, settings - in a single JSON file.

Declarative

Define everything in devcontainer.json

Reproducible

Same environment for every developer

Docker-Based

Built on Docker container technology

How DevContainers Relate to Docker

Standard Docker

  • Runs production workloads
  • Minimal images for efficiency
  • Usually stateless
  • Optimized for runtime

DevContainers

  • Runs development environments
  • Full tooling (git, debuggers, linters)
  • Persistent workspaces
  • Optimized for development

DevContainer Anatomy

The devcontainer.json File

{
  "name": "My Dev Container",
  "image": "mcr.microsoft.com/devcontainers/typescript-node:1-20-bullseye",

  // Or build from Dockerfile
  "build": {
    "dockerfile": "Dockerfile",
    "context": ".."
  },

  // Features - modular add-ons
  "features": {
    "ghcr.io/devcontainers/features/git:1": {},
    "ghcr.io/devcontainers/features/docker-in-docker:2": {}
  },

  // Lifecycle scripts
  "postCreateCommand": "npm install",
  "postStartCommand": "npm run dev",

  // VS Code customization
  "customizations": {
    "vscode": {
      "extensions": [
        "dbaeumer.vscode-eslint",
        "esbenp.prettier-vscode"
      ],
      "settings": {
        "editor.formatOnSave": true
      }
    }
  },

  // Port forwarding
  "forwardPorts": [3000, 5432],

  // Environment variables
  "containerEnv": {
    "NODE_ENV": "development"
  },

  // Mounts and volumes
  "mounts": [
    "source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind"
  ]
}

Dockerfile Integration

You can use pre-built images or define custom Dockerfiles for complete control:

# .devcontainer/Dockerfile
FROM ubuntu:22.04

# Install system dependencies
RUN apt-get update && apt-get install -y \
    curl \
    git \
    build-essential \
    python3 \
    python3-pip

# Install Node.js
RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
RUN apt-get install -y nodejs

# Create non-root user
ARG USERNAME=developer
RUN useradd -m -s /bin/bash $USERNAME

USER $USERNAME
WORKDIR /home/$USERNAME

Docker Compose Support

For multi-container setups (app + database + cache):

devcontainer.json
{
  "name": "Full Stack",
  "dockerComposeFile": "docker-compose.yml",
  "service": "app",
  "workspaceFolder": "/workspace"
}
docker-compose.yml
services:
  app:
    build: .
    volumes:
      - .:/workspace

  postgres:
    image: postgres:15
    environment:
      POSTGRES_PASSWORD: dev

  redis:
    image: redis:7-alpine

Features System

Features are self-contained, reusable units of installation code. Think of them as modular add-ons:

Git
devcontainers/features/git
Node.js
devcontainers/features/node
Python
devcontainers/features/python
Docker-in-Docker
devcontainers/features/docker-in-docker
kubectl
devcontainers/features/kubectl-helm
AWS CLI
devcontainers/features/aws-cli

Common Language Configurations

Click on a language to view its devcontainer.json configuration:

Python / Django
{
  "name": "Python Django",
  "image": "mcr.microsoft.com/devcontainers/python:3.11-bullseye",

  "features": {
    "ghcr.io/devcontainers/features/git:1": {},
    "ghcr.io/devcontainers/features/docker-in-docker:2": {}
  },

  "postCreateCommand": "pip install -r requirements.txt && python manage.py migrate",

  "customizations": {
    "vscode": {
      "extensions": [
        "ms-python.python",
        "ms-python.vscode-pylance",
        "ms-python.black-formatter",
        "batisteo.vscode-django"
      ]
    }
  },

  "forwardPorts": [8000],

  "containerEnv": {
    "DJANGO_SETTINGS_MODULE": "myproject.settings.dev"
  }
}
Node.js / React
{
  "name": "Node.js React",
  "image": "mcr.microsoft.com/devcontainers/typescript-node:1-20-bullseye",

  "features": {
    "ghcr.io/devcontainers/features/git:1": {},
    "ghcr.io/devcontainers/features/github-cli:1": {}
  },

  "postCreateCommand": "npm install",
  "postStartCommand": "npm run dev",

  "customizations": {
    "vscode": {
      "extensions": [
        "dbaeumer.vscode-eslint",
        "esbenp.prettier-vscode",
        "bradlc.vscode-tailwindcss"
      ],
      "settings": {
        "editor.formatOnSave": true,
        "editor.defaultFormatter": "esbenp.prettier-vscode"
      }
    }
  },

  "forwardPorts": [3000, 5173],

  "containerEnv": {
    "NODE_ENV": "development"
  }
}
Java / Spring Boot
{
  "name": "Java Spring Boot",
  "image": "mcr.microsoft.com/devcontainers/java:1-21-bullseye",

  "features": {
    "ghcr.io/devcontainers/features/git:1": {},
    "ghcr.io/devcontainers/features/maven:1": {
      "version": "3.9"
    },
    "ghcr.io/devcontainers/features/docker-in-docker:2": {}
  },

  "postCreateCommand": "./mvnw clean install -DskipTests",

  "customizations": {
    "vscode": {
      "extensions": [
        "vscjava.vscode-java-pack",
        "vmware.vscode-spring-boot",
        "vscjava.vscode-spring-initializr"
      ]
    }
  },

  "forwardPorts": [8080],

  "containerEnv": {
    "SPRING_PROFILES_ACTIVE": "dev"
  }
}
Go
{
  "name": "Go",
  "image": "mcr.microsoft.com/devcontainers/go:1.21-bullseye",

  "features": {
    "ghcr.io/devcontainers/features/git:1": {},
    "ghcr.io/devcontainers/features/docker-in-docker:2": {}
  },

  "postCreateCommand": "go mod download",

  "customizations": {
    "vscode": {
      "extensions": [
        "golang.go",
        "golang.go-nightly"
      ],
      "settings": {
        "go.toolsManagement.autoUpdate": true,
        "go.useLanguageServer": true
      }
    }
  },

  "forwardPorts": [8080],

  "containerEnv": {
    "CGO_ENABLED": "0"
  }
}
Rust
{
  "name": "Rust",
  "image": "mcr.microsoft.com/devcontainers/rust:1-1-bullseye",

  "features": {
    "ghcr.io/devcontainers/features/git:1": {}
  },

  "postCreateCommand": "cargo build",

  "customizations": {
    "vscode": {
      "extensions": [
        "rust-lang.rust-analyzer",
        "vadimcn.vscode-lldb",
        "serayuzgur.crates"
      ],
      "settings": {
        "rust-analyzer.checkOnSave.command": "clippy"
      }
    }
  },

  "forwardPorts": [8000]
}
.NET / C#
{
  "name": ".NET",
  "image": "mcr.microsoft.com/devcontainers/dotnet:1-8.0-bookworm",

  "features": {
    "ghcr.io/devcontainers/features/git:1": {},
    "ghcr.io/devcontainers/features/azure-cli:1": {}
  },

  "postCreateCommand": "dotnet restore && dotnet build",

  "customizations": {
    "vscode": {
      "extensions": [
        "ms-dotnettools.csharp",
        "ms-dotnettools.vscode-dotnet-runtime",
        "kreativ-software.csharpextensions"
      ]
    }
  },

  "forwardPorts": [5000, 5001],

  "containerEnv": {
    "ASPNETCORE_ENVIRONMENT": "Development"
  }
}

Advanced Features

Lifecycle Scripts

{
  "onCreateCommand": "git config --global ...",
  "updateContentCommand": "npm update",
  "postCreateCommand": "npm install",
  "postStartCommand": "npm run dev",
  "postAttachCommand": "echo 'Welcome!'"
}

Run commands at different stages of container lifecycle

VS Code Extensions

"customizations": {
  "vscode": {
    "extensions": [
      "dbaeumer.vscode-eslint",
      "esbenp.prettier-vscode"
    ],
    "settings": {
      "editor.formatOnSave": true
    }
  }
}

Auto-install extensions and configure settings

Port Forwarding

"forwardPorts": [3000, 5432],
"portsAttributes": {
  "3000": {
    "label": "Web App",
    "onAutoForward": "notify"
  },
  "5432": {
    "label": "PostgreSQL"
  }
}

Automatically forward ports with custom labels

Environment Variables

"containerEnv": {
  "NODE_ENV": "development",
  "DATABASE_URL": "postgres://..."
},
"remoteEnv": {
  "PATH": "${containerEnv:PATH}:/custom"
}

Set environment variables for container and remote sessions

Mounts & Volumes

"mounts": [
  "source=/var/run/docker.sock,
   target=/var/run/docker.sock,
   type=bind",
  "source=node_modules,
   target=${containerWorkspaceFolder}/node_modules,
   type=volume"
]

Bind mounts for Docker socket, named volumes for dependencies

GPU Support

"hostRequirements": {
  "gpu": "optional"
},
"runArgs": [
  "--gpus=all"
]

Enable GPU access for ML/AI workloads with CUDA support

Best Practices

Image Size Optimization

Use multi-stage builds and minimal base images. Alpine variants are smaller but may lack some tools.

# Use slim variants for smaller images
FROM node:20-slim  # ~250MB instead of node:20 (~1GB)

Layer Caching

Order Dockerfile commands from least to most frequently changing to maximize cache hits.

# Copy dependency files first (changes rarely)
COPY package*.json ./
RUN npm install
# Then copy source code (changes frequently)
COPY . .

Security Hardening

Always run as non-root user. Pin versions to avoid supply chain attacks.

# Create and use non-root user
RUN useradd -m -s /bin/bash developer
USER developer

# Pin feature versions
"features": {
  "ghcr.io/devcontainers/features/node:1": { "version": "20.11.0" }
}

Version Pinning

Pin all versions - base images, features, extensions - to ensure reproducibility.

# Pin base image with digest
FROM node:20.11.0-bullseye@sha256:abc123...

# Pin feature versions
"features": {
  "ghcr.io/devcontainers/features/git:1": { "version": "1.0.5" }
}

Documentation

Include README.md in .devcontainer/ explaining what is pre-configured and any special setup.

.devcontainer/
|-- devcontainer.json
|-- Dockerfile
|-- docker-compose.yml
+-- README.md  # Document your setup!

DevContainers Across Platforms

Platform Support Location Notes
VS Code (Local)
Full Local Docker Native support via Remote Containers extension
GitHub Codespaces
Full Cloud (GitHub) Native support, reads from .devcontainer/
Gitpod
Partial Cloud (Gitpod) Prefers .gitpod.yml but supports devcontainer.json
Coder
Full Self-hosted Via Terraform + Envbuilder agent
DevPod
Full Multi-cloud Open-source client for any cloud
JetBrains Gateway
Partial Remote SSH Can connect to existing containers

Publishing & Sharing DevContainers

Container Registries

Publish images to Docker Hub, GitHub Container Registry (GHCR), or private registries.

Docker Hub
GitHub Container Registry
Private registries

Template Repositories

Create GitHub template repos with .devcontainer/ that teams can clone and customize.

my-team-template/
|-- .devcontainer/
|   |-- devcontainer.json
|   +-- Dockerfile
+-- README.md

Organization Standards

Platform teams can publish standard images and feature sets for the entire organization.

  • Pre-approved tools
  • Security scanning
  • Compliance standards

Publishing to GitHub Container Registry

# Build and tag your image
docker build -t ghcr.io/myorg/python-dev:latest .devcontainer

# Login to GitHub Container Registry
echo $GITHUB_TOKEN | docker login ghcr.io -u USERNAME --password-stdin

# Push the image
docker push ghcr.io/myorg/python-dev:latest

# Reference in devcontainer.json
{
  "image": "ghcr.io/myorg/python-dev:latest"
}