Developer Tools

DevContainers: Consistent Development Environments Across Teams

],
"settings": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"eslint.validate": ["javascript", "typescript"]
}
}```
},
"forwardPorts": [3000, 9229],
"postCreateCommand": "npm install",
"remoteUser": "node"
}


### Custom Dockerfile

**`.devcontainer/Dockerfile`:**

```dockerfile
FROM mcr.microsoft.com/devcontainers/python:3.11

# Install system dependencies
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
```text
&& apt-get -y install --no-install-recommends \
   postgresql-client \
   redis-tools \
   curl \
   jq

Install Python tools

RUN pip install --upgrade pip \

&& pip install black pylint pytest pytest-cov

Install Python tools

Setup non-root user

ARG USERNAME=vscode
ARG USER_UID=1000
ARG USER_GID=$USER_UID

Setup non-root user

USER $USERNAME

Configure shell

RUN echo 'export PS1="[\e[32m](devcontainer)[\e[m] \w $ "' >> ~/.bashrc

Configure shell


**`devcontainer.json` with Dockerfile:**

```json
{
  "name": "Python Development",
  "build": {
```text
"dockerfile": "Dockerfile",
"args": {
  "USERNAME": "vscode"
}```
  },
  "customizations": {
```text
"vscode": {
  "extensions": [
    "ms-python.python",
    "ms-python.vscode-pylance",
    "ms-python.black-formatter"
  ]
}```
  },
  "postCreateCommand": "pip install -r requirements.txt",
  "remoteUser": "vscode"
}

Multi-Container Development

Docker Compose Integration

Multi-Container Development

.devcontainer/docker-compose.yml:

version: '3.8'

services:
  app:
```yaml
build:
  context: ..
  dockerfile: .devcontainer/Dockerfile
volumes:
  - ..:/workspace:cached
command: sleep infinity
networks:
  - dev-network
depends_on:
  - db
  - redis

db:

image: postgres:16
restart: unless-stopped
environment:
  POSTGRES_USER: devuser
  POSTGRES_PASSWORD: devpassword
  POSTGRES_DB: devdb
volumes:
  - postgres-data:/var/lib/postgresql/data
networks:
  - dev-network

redis:

image: redis:7
restart: unless-stopped
networks:
  - dev-network

volumes:
postgres-data:

networks:
dev-network:


**`devcontainer.json` with Compose:**

```json
{
  "name": "Full Stack Development",
  "dockerComposeFile": "docker-compose.yml",
  "service": "app",
  "workspaceFolder": "/workspace",
  "customizations": {
```text
"vscode": {
  "extensions": [
    "ms-azuretools.vscode-docker",
    "ms-python.python",
    "cweijan.vscode-postgresql-client2"
  ]
}```
  },
  "forwardPorts": [8000, 5432, 6379],
  "postCreateCommand": "pip install -r requirements.txt && python manage.py migrate",
  "remoteUser": "vscode"
}

Language-Specific Configurations

Python with Virtual Environment

Language-Specific Configurations

.devcontainer/devcontainer.json:

{
  "name": "Python 3.11",
  "image": "mcr.microsoft.com/devcontainers/python:3.11",
  "features": {
```text
"ghcr.io/devcontainers/features/common-utils:2": {
  "installZsh": true,
  "configureZshAsDefaultShell": true
}```
  },
  "customizations": {
```text
"vscode": {
  "extensions": [
    "ms-python.python",
    "ms-python.vscode-pylance",
    "ms-python.black-formatter",
    "ms-python.isort",
    "njpwerner.autodocstring"
  ],
  "settings": {
    "python.defaultInterpreterPath": "/usr/local/bin/python",
    "python.linting.enabled": true,
    "python.linting.pylintEnabled": true,
    "python.formatting.provider": "black",
    "python.testing.pytestEnabled": true,
    "[python]": {
      "editor.formatOnSave": true,
      "editor.codeActionsOnSave": {
        "source.organizeImports": true
      }
    }
  }
}```
  },
  "postCreateCommand": "pip install -r requirements.txt -r requirements-dev.txt",
  "postStartCommand": "python --version && pip list"
}

.NET with SDK

.devcontainer/devcontainer.json:

{
  "name": ".NET 8.0",
  "image": "mcr.microsoft.com/devcontainers/dotnet:8.0",
  "features": {
```text
"ghcr.io/devcontainers/features/azure-cli:1": {},
"ghcr.io/devcontainers/features/powershell:1": {}```
  },
  "customizations": {
```text
"vscode": {
  "extensions": [
    "ms-dotnettools.csharp",
    "ms-dotnettools.csdevkit",
    "ms-dotnettools.vscode-dotnet-runtime",
    "visualstudioexptteam.vscodeintellicode-csharp"
  ],
  "settings": {
    "omnisharp.enableRoslynAnalyzers": true,
    "omnisharp.enableEditorConfigSupport": true,
    "dotnet.defaultSolution": "MyApp.sln"
  }
}```
  },
  "postCreateCommand": "dotnet restore && dotnet build",
  "remoteUser": "vscode"
}

Node.js with npm/Yarn

.devcontainer/devcontainer.json:

{
  "name": "Node.js 20 with TypeScript",
  "image": "mcr.microsoft.com/devcontainers/typescript-node:20",
  "features": {
```text
"ghcr.io/devcontainers/features/node:1": {
  "version": "20",
  "nodeGypDependencies": true
}```
  },
  "customizations": {
```text
"vscode": {
  "extensions": [
    "dbaeumer.vscode-eslint",
    "esbenp.prettier-vscode",
    "ms-vscode.vscode-typescript-next",
    "orta.vscode-jest"
  ],
  "settings": {
    "editor.formatOnSave": true,
    "editor.codeActionsOnSave": {
      "source.fixAll.eslint": true
    },
    "typescript.tsdk": "node_modules/typescript/lib"
  }
}```
  },
  "postCreateCommand": "npm install",
  "postStartCommand": "npm run dev",
  "forwardPorts": [3000, 5173],
  "portsAttributes": {
```text
"3000": {
  "label": "Application",
  "onAutoForward": "notify"
}```
  }
}

Java with Maven

.devcontainer/devcontainer.json:

{
  "name": "Java 21 with Maven",
  "image": "mcr.microsoft.com/devcontainers/java:21",
  "features": {
```text
"ghcr.io/devcontainers/features/java:1": {
  "version": "21",
  "installMaven": true,
  "installGradle": false
}```
  },
  "customizations": {
```text
"vscode": {
  "extensions": [
    "vscjava.vscode-java-pack",
    "vscjava.vscode-spring-boot-dashboard",
    "vmware.vscode-spring-boot"
  ],
  "settings": {
    "java.configuration.runtimes": [
      {
        "name": "JavaSE-21",
        "path": "/usr/local/sdkman/candidates/java/current"
      }
    ]
  }
}```
  },
  "postCreateCommand": "mvn clean install -DskipTests",
  "forwardPorts": [8080]
}

VS Code Integration

Remote - Containers Extension

VS Code Integration

Installation:

## Install extension
code --install-extension ms-vscode-remote.remote-containers

![Install extension](/images/articles/developer-tools/2025-12-08-devcontainers-consistent-development-environments-across-teams-sec7-implementation.jpg)



> **Architecture Overview:** **Usage:**

{
  "version": "0.2.0",
  "configurations": [
```json
{
  "name": "Python: FastAPI",
  "type": "python",
  "request": "launch",
  "module": "uvicorn",
  "args": [
    "main:app",
    "--reload",
    "--host", "0.0.0.0",
    "--port", "8000"
  ],
  "jinja": true,
  "justMyCode": false
},
{
  "name": "Node: Debug",
  "type": "node",
  "request": "launch",
  "program": "${workspaceFolder}/src/index.js",
  "restart": true,
  "console": "integratedTerminal"
}```
  ]
}

Tasks Configuration

.vscode/tasks.json:

{
  "version": "2.0.0",
  "tasks": [
```json
{
  "label": "Run Tests",
  "type": "shell",
  "command": "pytest tests/ -v --cov",
  "group": {
    "kind": "test",
    "isDefault": true
  },
  "presentation": {
    "reveal": "always",
    "panel": "new"
  }
},
{
  "label": "Start Database",
  "type": "shell",
  "command": "docker-compose up -d db",
  "problemMatcher": []
}```
  ]
}

GitHub Codespaces Integration

Configuration

GitHub Codespaces Integration

.devcontainer/devcontainer.json for Codespaces:

{
  "name": "Codespaces Python",
  "image": "mcr.microsoft.com/devcontainers/python:3.11",
  "hostRequirements": {
```text
"cpus": 4,
"memory": "8gb",
"storage": "32gb"```
  },
  "customizations": {
```text
"codespaces": {
  "openFiles": [
    "README.md",
    "src/main.py"
  ]
}```
  },
  "secrets": {
```text
"GITHUB_TOKEN": {
  "description": "GitHub Personal Access Token"
}```
  },
  "postCreateCommand": "pip install -r requirements.txt && pre-commit install"
}

Lifecycle Scripts

.devcontainer/lifecycle/postCreate.sh:

#!/bin/bash

echo "Setting up development environment..."

## Install dependencies
pip install -r requirements.txt

![Install dependencies](/images/articles/developer-tools/2025-12-08-devcontainers-consistent-development-environments-across-teams-sec10-implementation.jpg)


## Setup pre-commit hooks
pre-commit install

![Setup pre-commit hooks](/images/articles/developer-tools/2025-12-08-devcontainers-consistent-development-environments-across-teams-sec11-implementation.jpg)


## Initialize database
python manage.py migrate

![Initialize database](/images/articles/developer-tools/2025-12-08-devcontainers-consistent-development-environments-across-teams-sec12-database.jpg)


## Create sample data
python manage.py loaddata fixtures/sample_data.json

![Create sample data](/images/articles/developer-tools/2025-12-08-devcontainers-consistent-development-environments-across-teams-sec13-implementation.jpg)


echo "Setup complete! Ready to code."

Reference in devcontainer.json:

{
  "postCreateCommand": "bash .devcontainer/lifecycle/postCreate.sh",
  "postStartCommand": "python manage.py runserver 0.0.0.0:8000",
  "postAttachCommand": "git status"
}

Performance Optimization

Volume Mounts

Performance Optimization

Cached Mounts:

{
  "mounts": [
```text
"source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=cached"```
  ]
}

Named Volumes for Dependencies:

{
  "mounts": [
```text
"source=node_modules,target=${containerWorkspaceFolder}/node_modules,type=volume",
"source=pip-cache,target=/home/vscode/.cache/pip,type=volume"```
  ]
}

BuildKit Cache

.devcontainer/Dockerfile with cache:

## syntax=docker/dockerfile:1
FROM mcr.microsoft.com/devcontainers/python:3.11

![syntax=docker/dockerfile:1](/images/articles/developer-tools/2025-12-08-devcontainers-consistent-development-environments-across-teams-sec15-container.jpg)


## Cache pip dependencies
RUN --mount=type=cache,target=/root/.cache/pip \
```python
pip install --upgrade pip setuptools wheel

Cache pip dependencies

Copy and install requirements with cache

COPY requirements.txt /tmp/
RUN --mount=type=cache,target=/root/.cache/pip \

pip install -r /tmp/requirements.txt

![Copy and install requirements with cache](/images/articles/developer-tools/2025-12-08-devcontainers-consistent-development-environments-across-teams-sec17-implementation.jpg)


## Layer Optimization

```dockerfile

![Layer Optimization](/images/articles/developer-tools/2025-12-08-devcontainers-consistent-development-environments-across-teams-sec18-bestpractice.jpg)


## Bad: Combines unrelated operations
RUN apt-get update && apt-get install -y \
```python
postgresql-client \
&& pip install django

Bad: Combines unrelated operations

Good: Separate layers for caching

RUN apt-get update && apt-get install -y postgresql-client
RUN pip install django

Good: Separate layers for caching


## Team Adoption

### Documentation

![Team Adoption](/images/articles/developer-tools/2025-12-08-devcontainers-consistent-development-environments-across-teams-sec21-generic.jpg)


**`DEVCONTAINER_SETUP.md`:**


> **Architecture Overview:** ## DevContainer Setup


## Clear Docker cache

docker system prune -a --volumes

![Clear Docker cache](/images/articles/developer-tools/2025-12-08-devcontainers-consistent-development-environments-across-teams-sec26-performance.jpg)


```text

## Port Already in Use

Edit `.devcontainer/devcontainer.json` and change `forwardPorts`.

![Port Already in Use](/images/articles/developer-tools/2025-12-08-devcontainers-consistent-development-environments-across-teams-sec27-implementation.jpg)

Sharing Configurations

.devcontainer/devcontainer.json in version control:

## Commit devcontainer configuration
git add .devcontainer/
git commit -m "Add DevContainer configuration"
git push origin main

![Commit devcontainer configuration](/images/articles/developer-tools/2025-12-08-devcontainers-consistent-development-environments-across-teams-sec28-implementation.jpg)

Expected output:

To https://github.com/contoso/myapp.git
   abc1234..def5678  main -> main

Terminal output for git push

Organization Templates:

## Create template repository
git clone https://github.com/contoso/devcontainer-templates.git
cp -r devcontainer-templates/python/.devcontainer ./

![Create template repository](/images/articles/developer-tools/2025-12-08-devcontainers-consistent-development-environments-across-teams-sec29-implementation.jpg)

Best Practices

  1. Version Control Everything: Commit all .devcontainer files to repository
  2. Use Official Images: Prefer mcr.microsoft.com/devcontainers/* images
  3. Minimal Base Images: Start with minimal images, add only required tools
  4. Non-Root User: Always specify remoteUser for security
  5. Port Forwarding: Document all forwarded ports in README
  6. Lifecycle Scripts: Use postCreateCommand for one-time setup only
  7. Secrets Management: Never hardcode secrets in devcontainer.json

Best Practices

Troubleshooting

Troubleshooting

Figure: Configuration and management dashboard with status overview.

Container Build Timeout:

Architecture Overview: ## Increase Docker memory allocation

Permission Errors:

{
  "remoteUser": "vscode",
  "containerUser": "vscode",
  "updateRemoteUserUID": true
}

Extension Not Loading:

Architecture Overview: ## Reinstall extensions in container

Architecture Decision and Tradeoffs

When designing development workflow solutions with Developer Tools, consider these key architectural trade-offs:

Approach Best For Tradeoff
Managed / platform service Rapid delivery, reduced ops burden Less customisation, potential vendor lock-in
Custom / self-hosted Full control, advanced tuning Higher operational overhead and cost

Recommendation: Start with the managed approach for most workloads and move to custom only when specific requirements demand it.

Validation and Versioning

  • Last validated: April 2026
  • Validate examples against your tenant, region, and SKU constraints before production rollout.
  • Keep module, CLI, and SDK versions pinned in automation pipelines and review quarterly.

Security and Governance Considerations

  • Apply least-privilege access using RBAC roles and just-in-time elevation for admin tasks.
  • Store secrets in managed secret stores and avoid embedding credentials in scripts or source files.
  • Enable audit logging, data protection policies, and periodic access reviews for regulated workloads.

Cost and Performance Notes

  • Define budgets and alerts, then monitor usage and cost trends continuously after go-live.
  • Baseline performance with synthetic and real-user checks before and after major changes.
  • Scale resources with measured thresholds and revisit sizing after usage pattern changes.

Official Microsoft References

Public Examples from Official Sources

Key Takeaways

  • DevContainers eliminate "works on my machine" problems with reproducible environments
  • Configuration as code enables consistent development across teams
  • Docker Compose supports multi-container development with databases and services
  • GitHub Codespaces provides cloud-based DevContainer environments
  • Performance optimizations like cached mounts and BuildKit reduce rebuild times

Key Takeaways

Next Steps

  • Explore Features for reusable DevContainer components
  • Implement Dev Container Templates for common project types
  • Integrate GitHub Actions to validate DevContainer builds in CI
  • Configure Pre-commit hooks within DevContainers for code quality

Additional Resources


Build once, develop anywhere.

AI Assistant
AI Assistant

Article Assistant

Ask me about this article

AI
Hi! I'm here to help you understand this article. Ask me anything about the content, concepts, or implementation details.