Maîtriser les conteneurs Dev dans VS Code

Créez des environnements de développement cohérents, portables et reproductibles à l'aide des conteneurs de développement.

Sommaire

Les développeurs se heurtent souvent au dilemme « fonctionne sur ma machine » en raison de désaccords de dépendances, de versions d’outils ou de différences d’OS.
Dev Containers dans Visual Studio Code (VS Code) résolvent cela de manière élégante — en vous permettant de développer dans un environnement conteneurisé configuré spécifiquement pour votre projet.

Le développement logiciel moderne exige des environnements cohérents et reproductibles qui fonctionnent sur toutes les machines et systèmes d’exploitation. Que vous travailliez sur un projet de science des données en Python, une application web en Node.js ou un microservice en Go, assurer que chaque membre de l’équipe a un environnement de développement identique peut être un défi.

vs code dev containers

Ce guide complet vous explique ce sont les Dev Containers, pourquoi ils sont précieux et comment les configurer dans VS Code pour des flux de travail de développement portables et fluides. Vous apprendrez tout, des configurations de base aux configurations avancées avec Docker Compose et aux bonnes pratiques pour la collaboration d’équipe.


🧩 Qu’est-ce que les Dev Containers ?

Les Dev Containers sont une fonction fournie par l’extension VS Code Remote - Containers (maintenant partie de VS Code Remote Development).
Ils vous permettent d’ouvrir votre projet dans un conteneur Docker préconfiguré avec toutes vos dépendances, langages et outils.

Pensez-y comme :

“Un environnement de développement entièrement configuré, défini comme du code.”

Au lieu d’installer Python, Node.js, des bases de données et divers outils directement sur votre machine, vous les définissez dans des fichiers de configuration. Lorsque vous ouvrez le projet dans VS Code, il démarre automatiquement un conteneur avec tout ce qui est préinstallé et configuré exactement comme spécifié.

Une configuration de Dev Container typique inclut :

  • Un Dockerfile ou une référence à une image de base (définissant le système d’exploitation du conteneur, les langages et les outils)
  • Un fichier devcontainer.json (configurant les paramètres de l’espace de travail, les extensions VS Code, le transfert de ports, les variables d’environnement et les commandes de démarrage)
  • Un docker-compose.yml optionnel si votre projet dépend de plusieurs services (comme des bases de données, Redis, des files d’attente de messages, etc.)

⚙️ Pourquoi utiliser les Dev Containers ?

Voici ce qui les rend puissants :

  • Reproductibilité : Chaque développeur et chaque système CI utilise exactement le même environnement. Plus de problèmes comme « ça fonctionne sur ma machine mais pas sur la vôtre ». Ce qui fonctionne sur votre ordinateur fonctionnera exactement de la même manière sur l’ordinateur de votre collègue, qu’il s’agisse d’un Windows, d’un Mac ou d’un ordinateur Linux.

  • Isolation : Aucun besoin de polluer votre machine locale avec des dépendances conflictuelles. Travailler sur plusieurs projets nécessitant différentes versions de Python, Node.js ou d’autres outils sans conflits de version ou sans jongler avec des environnements virtuels.

  • Portabilité : Fonctionne sur tout OS qui prend en charge Docker. Votre environnement de développement voyage avec votre code. Clonez un dépôt, ouvrez-le dans VS Code, et vous êtes prêt à coder en quelques minutes — indépendamment de votre système d’exploitation.

  • Consistance d’équipe : Une configuration partagée à travers toute votre équipe. Les nouveaux membres de l’équipe peuvent être opérationnels en quelques minutes au lieu de passer des heures (ou des jours) à configurer leur environnement de développement avec les bons outils et versions.

  • Automatisation : Installe automatiquement les extensions VS Code, les dépendances linguistiques et les outils lors de l’ouverture du projet. Les commandes post-creation peuvent exécuter des migrations de base de données, insérer des données ou effectuer d’autres tâches de configuration sans intervention manuelle.

  • Sécurité : Isoler les dépendances potentiellement risquées dans des conteneurs. Si vous avez besoin de tester avec une ancienne version vulnérable d’une bibliothèque, elle reste contenue et n’affecte pas votre système hôte.

Exemple concret : Imaginez rejoindre une équipe travaillant sur un projet de microservices qui utilise Python 3.11, PostgreSQL 15, Redis et Elasticsearch. Sans Dev Containers, vous passeriez des heures à installer et configurer chaque composant. Avec Dev Containers, vous ouvrez le projet dans VS Code, laissez-le construire le conteneur, et vous êtes en train d’écrire du code en 5 à 10 minutes.


🧱 Configuration d’un Dev Container dans VS Code

Allons-y étape par étape.

1. Installer les outils requis

Avant de commencer, assurez-vous que les éléments suivants sont installés :

  • Docker Desktop (ou un runtime conteneur équivalent comme Podman)

    • Pour Windows/Mac : Téléchargez et installez Docker Desktop
    • Pour Linux : Installez Docker Engine et assurez-vous que votre utilisateur fait partie du groupe docker
  • VS Code (version la plus récente recommandée)

  • L’extension Dev Containers (par Microsoft)

    • Ouvrez VS Code
    • Allez dans Extensions (Ctrl+Shift+X ou Cmd+Shift+X sur macOS)
    • Recherchez “Dev Containers”
    • Installez l’extension avec l’ID : ms-vscode-remote.remote-containers

Vérifiez votre configuration :

# Vérifiez que Docker est en cours d'exécution
docker --version
docker ps

# Devrait afficher la version Docker et les conteneurs en cours d'exécution (s'il y en a)

2. Initialiser le Dev Container

Ouvrez le dossier de votre projet dans VS Code et ouvrez le Palette de commandes (Ctrl+Shift+P ou Cmd+Shift+P sur macOS), puis tapez et sélectionnez :

Dev Containers: Ajouter des fichiers de configuration Dev Container...

VS Code affichera une liste de modèles d’environnement prédéfinis. Choisissez celui qui correspond à votre projet :

  • Node.js — Projets JavaScript/TypeScript
  • Python — Sciences des données, applications web, scripts
  • Go — Applications et services Go
  • .NET — Applications C#/F#
  • Java — Projets Spring Boot, Maven, Gradle
  • Docker-in-Docker — Lorsque vous avez besoin de Docker à l’intérieur de votre conteneur
  • Et bien plus encore…

Vous pouvez également sélectionner des fonctionnalités supplémentaires comme :

  • Outils courants (git, curl, wget)
  • Clients de base de données
  • Outils CLI cloud (AWS, Azure, GCP)

Ce générateur crée un dossier .devcontainer avec :

  • devcontainer.json — Fichier de configuration principal
  • Dockerfile — Définition d’image personnalisée (ou une référence à une image de base prédéfinie)

3. Personnaliser devcontainer.json

Le fichier devcontainer.json est le lieu où tout se passe. Voici un exemple bien documenté pour un projet Node.js :

{
  // Nom d'affichage du conteneur dans VS Code
  "name": "Conteneur de développement Node.js",
  
  // Configuration de construction - peut utiliser Dockerfile ou une image prédéfinie
  "build": {
    "dockerfile": "Dockerfile",
    "context": ".."
  },
  
  // Alternative : utiliser une image prédéfinie au lieu d'un Dockerfile
  // "image": "mcr.microsoft.com/devcontainers/javascript-node:18",
  
  // Configuration de l'espace de travail
  "customizations": {
    "vscode": {
      // Paramètres VS Code applicables dans le conteneur
      "settings": {
        "terminal.integrated.defaultProfile.linux": "bash",
        "editor.formatOnSave": true,
        "editor.defaultFormatter": "esbenp.prettier-vscode"
      },
      
      // Extensions à installer automatiquement
      "extensions": [
        "dbaeumer.vscode-eslint",
        "esbenp.prettier-vscode",
        "eamodio.gitlens",
        "ms-azuretools.vscode-docker"
      ]
    }
  },
  
  // Transfert de ports - rendre les ports du conteneur accessibles sur l'hôte
  "forwardPorts": [3000, 5432],
  "portsAttributes": {
    "3000": {
      "label": "Application",
      "onAutoForward": "notify"
    }
  },
  
  // Commandes à exécuter à différentes étapes
  "postCreateCommand": "npm install",     // Après la création du conteneur
  "postStartCommand": "npm run dev",      // Après le démarrage du conteneur
  
  // Variables d'environnement
  "containerEnv": {
    "NODE_ENV": "développement",
    "PORT": "3000"
  },
  
  // Exécuter le conteneur en tant qu'utilisateur non root (recommandé pour la sécurité)
  "remoteUser": "node",
  
  // Monter des volumes supplémentaires
  "mounts": [
    "source=${localEnv:HOME}/.ssh,target=/home/node/.ssh,readonly,type=bind"
  ]
}

Explication des options de configuration clés :

  • name — Nom d’affichage affiché dans la barre d’état de VS Code
  • build / image — Utiliser un Dockerfile ou une image prédéfinie
  • customizations.vscode.extensions — Extensions VS Code à installer automatiquement
  • forwardPorts — Ports à exposer depuis le conteneur vers l’hôte
  • postCreateCommand — S’exécute une fois que le conteneur est créé (ex. : npm install, pip install -r requirements.txt)
  • postStartCommand — S’exécute chaque fois que le conteneur démarre
  • containerEnv — Variables d’environnement disponibles dans le conteneur
  • remoteUser — Compte utilisateur à utiliser à l’intérieur du conteneur
  • mounts — Fichiers/dossiers supplémentaires à monter (comme les clés SSH)

💡 Conseils pro :

  • Utilisez postCreateCommand pour les opérations lentes (npm install, pip install)
  • Utilisez postStartCommand pour les tâches de démarrage rapides (migrations de base de données)
  • Spécifiez toujours les extensions nécessaires à votre projet — cela garantit un outillage cohérent
  • Utilisez des variables d’environnement pour la configuration qui diffère entre les développeurs

4. Construire et ouvrir dans le conteneur

Une fois votre configuration prête, il est temps de lancer votre environnement de développement :

Ouvrez la Palette de commandes (Ctrl+Shift+P / Cmd+Shift+P) et exécutez :

Dev Containers: Reouvrir dans le conteneur

Ce qui se passe ensuite :

  1. Construction de l’image — VS Code construit l’image Docker basée sur votre Dockerfile ou tire une image prédéfinie. Cela peut prendre quelques minutes la première fois.

  2. Création du conteneur — Docker crée un nouveau conteneur à partir de l’image construite.

  3. Montage des volumes — Votre dossier de projet est monté dans le conteneur, rendant votre code accessible à l’intérieur.

  4. Installation des extensions — Toutes les extensions VS Code spécifiées sont installées automatiquement dans le conteneur.

  5. Commandes post-creation — Votre postCreateCommand s’exécute (ex. : npm install, pip install -r requirements.txt).

  6. Prêt ! — VS Code se reconnecte au conteneur, et vous êtes maintenant en développement à l’intérieur.

Vérifiez que vous êtes dans le conteneur :

Vous pouvez confirmer que vous travaillez à l’intérieur du conteneur en ouvrant un terminal et en exécutant :

# Vérifiez le système d'exploitation
uname -a
# Sortie : Linux ... (noyau du conteneur)

# Vérifiez le nom d'hôte (généralement l'ID du conteneur)
hostname
# Sortie : abc123def456

# Vérifiez les processus en cours d'exécution
ps aux
# Vous verrez les processus du conteneur, pas ceux de votre système hôte

Remarquez que la barre d’état de VS Code (en bas à gauche) affiche maintenant : Dev Container : [Nom de votre conteneur]

Commandes du cycle de vie du conteneur :

  • Reconstruire le conteneurDev Containers: Reconstruire le conteneur (lorsque vous modifiez le Dockerfile)
  • Reconstruire sans cacheDev Containers: Reconstruire le conteneur sans cache (pour une construction fraîche)
  • Reouvrir localementDev Containers: Reouvrir le dossier localement (quitter le conteneur, travailler sur l’hôte)

5. Ajouter des services supplémentaires (optionnel)

Les applications réelles dépendent souvent de bases de données, de couches de mise en cache, de files d’attente ou d’autres services. Vous pouvez utiliser Docker Compose pour orchestrer plusieurs conteneurs.

Exemple : Application full-stack avec Node.js, PostgreSQL et Redis

Créez un docker-compose.yml dans votre dossier .devcontainer :

version: "3.8"

services:
  # Conteneur de développement principal
  app:
    build: 
      context: ..
      dockerfile: .devcontainer/Dockerfile
    
    volumes:
      # Montage du dossier de projet
      - ..:/workspace:cached
      # Utilisez un volume nommé pour node_modules (meilleure performance)
      - node_modules:/workspace/node_modules
    
    # Gardez le conteneur en cours d'exécution
    command: sleep infinity
    
    # Accès réseau aux autres services
    depends_on:
      - db
      - redis
    
    environment:
      DATABASE_URL: postgresql://dev:secret@db:5432/appdb
      REDIS_URL: redis://redis:6379

  # Base de données PostgreSQL
  db:
    image: postgres:15-alpine
    restart: unless-stopped
    volumes:
      - postgres-data:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: dev
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: appdb
    ports:
      - "5432:5432"

  # Cache Redis
  redis:
    image: redis:7-alpine
    restart: unless-stopped
    volumes:
      - redis-data:/data
    ports:
      - "6379:6379"

volumes:
  postgres-data:
  redis-data:
  node_modules:

Puis, mettez à jour votre devcontainer.json pour utiliser Docker Compose :

{
  "name": "Environnement de développement full-stack",
  
  // Utilisez docker-compose au lieu d'un conteneur unique
  "dockerComposeFile": "docker-compose.yml",
  
  // Quel service utiliser comme conteneur de développement
  "service": "app",
  
  // Chemin vers le dossier de l'espace de travail à l'intérieur du conteneur
  "workspaceFolder": "/workspace",
  
  "customizations": {
    "vscode": {
      "extensions": [
        "dbaeumer.vscode-eslint",
        "esbenp.prettier-vscode",
        "ms-azuretools.vscode-docker",
        "ckolkman.vscode-postgres"  // Client PostgreSQL
      ]
    }
  },
  
  "forwardPorts": [3000, 5432, 6379],
  
  "postCreateCommand": "npm install && npm run db:migrate",
  
  "remoteUser": "node"
}

Ce que cette configuration fournit :

  • app — Votre conteneur de développement avec Node.js
  • db — Base de données PostgreSQL, accessible à db:5432 depuis votre application
  • redis — Cache Redis, accessible à redis:6379
  • Volumes nommés — Persister les données de la base de données entre les redémarrages du conteneur
  • Transfert de ports — Accédez à tous les services depuis votre machine hôte

Se connecter aux services depuis votre code :

// Dans votre application Node.js
const { Pool } = require('pg');
const redis = require('redis');

// Connexion à PostgreSQL
const pool = new Pool({
  connectionString: process.env.DATABASE_URL
  // Résout à : postgresql://dev:secret@db:5432/appdb
});

// Connexion à Redis
const redisClient = redis.createClient({
  url: process.env.REDIS_URL
  // Résout à : redis://redis:6379
});

Accéder aux services depuis votre machine hôte :

  • App : http://localhost:3000
  • PostgreSQL : localhost:5432 (en utilisant tout client PostgreSQL)
  • Redis : localhost:6379 (en utilisant redis-cli ou des outils graphiques)

Maintenant, lorsqu’on ouvre le projet dans VS Code, tous les services démarrent automatiquement !


🧠 Conseils avancés et bonnes pratiques

Utiliser des images préconstruites

Gagnez un temps de construction significatif en commençant par les images officielles de devcontainer de Microsoft :

{
  "image": "mcr.microsoft.com/devcontainers/python:3.11",
  "features": {
    "ghcr.io/devcontainers/features/git:1": {},
    "ghcr.io/devcontainers/features/github-cli:1": {}
  }
}

Features sont des scripts d’installation réutilisables pour des outils courants (Git, GitHub CLI, Node, AWS CLI, etc.).

Bonnes pratiques de gestion de version

Commitez toujours votre dossier .devcontainer :

git add .devcontainer/
git commit -m "Ajouter la configuration Dev Container"
git push

Cela garantit :

  • ✅ Les nouveaux membres de l’équipe obtiennent automatiquement l’environnement
  • ✅ Les changements d’environnement sont suivis et révisables
  • ✅ Tout le monde développe dans la même configuration

Conseil pro : Ajoutez une section README expliquant la configuration du conteneur de développement :


## Configuration de développement

Ce projet utilise les Dev Containers de VS Code. Pour commencer :

1. Installez Docker Desktop et VS Code
2. Installez l'extension "Dev Containers"
3. Clonez ce dépôt
4. Ouvrez-le dans VS Code
5. Cliquez sur "Reouvrir dans le conteneur" lorsqu'on vous le demande

Débogage dans les conteneurs

Le débogage fonctionne sans problème. Configurez votre launch.json comme d’habitude :

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Lancer Node.js",
      "type": "node",
      "request": "launch",
      "program": "${workspaceFolder}/index.js",
      "skipFiles": ["<node_internals>/**"]
    }
  ]
}

Définissez des points d’arrêt et déboguez normalement — VS Code gère automatiquement la connexion au conteneur.

Parité avec la CI/CD

Utilisez la même image de conteneur dans votre pipeline CI/CD :

# Exemple GitHub Actions
name: CI
on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    container:
      image: mcr.microsoft.com/devcontainers/javascript-node:18
    steps:
      - uses: actions/checkout@v3
      - run: npm install
      - run: npm test

Cela garantit une parité dev/prod — si les tests passent localement, ils passeront en CI.

Optimisation des performances

Pour les utilisateurs macOS/Windows — utilisez des volumes nommés pour les dépendances :

{
  "mounts": [
    "source=myproject-node_modules,target=${containerWorkspaceFolder}/node_modules,type=volume"
  ]
}

Cela améliore significativement les performances d’E/S pour node_modules, venv, etc.

Développement multi-étapes

Créez différentes configurations pour différents rôles d’équipe :

.devcontainer/
├── devcontainer.json          # Défaut (full-stack)
├── frontend/
│   └── devcontainer.json      # Frontend uniquement (plus léger)
└── backend/
    └── devcontainer.json      # Backend uniquement (avec DB)

Les membres de l’équipe peuvent choisir leur environnement lorsqu’ils ouvrent le projet.

Travailler avec les clés SSH et Git

Montez vos clés SSH pour les opérations Git :

{
  "mounts": [
    "source=${localEnv:HOME}${localEnv:USERPROFILE}/.ssh,target=/home/node/.ssh,readonly,type=bind"
  ],
  "postCreateCommand": "ssh-add ~/.ssh/id_ed25519 || true"
}

Fichiers d’environnement personnalisés

Chargez la configuration spécifique à l’environnement :

{
  "runArgs": ["--env-file", ".devcontainer/.env"]
}

.devcontainer/.env :

API_KEY=dev_key_here
DEBUG=true
LOG_LEVEL=debug

🔧 Résolution des problèmes courants

Le conteneur ne démarre pas

Erreur : Impossible de se connecter au démon Docker

Solution :

  • Assurez-vous que Docker Desktop est en cours d’exécution
  • Sur Linux, vérifiez : sudo systemctl status docker
  • Vérifiez que Docker est dans votre PATH : docker --version

Performance lente sur macOS/Windows

Problème : Les opérations de fichiers sont lentes

Solutions :

  1. Utilisez des volumes nommés pour node_modules, venv, etc.

  2. Activez le partage de fichiers dans les paramètres de Docker Desktop

  3. Considérez l’utilisation des options de montage cached ou delegated :

    "workspaceMount": "source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=cached"
    

Extensions non installées

Problème : Les extensions spécifiées dans devcontainer.json ne s’installent pas

Solutions :

  1. Reconstruisez le conteneur : Dev Containers: Reconstruire le conteneur
  2. Vérifiez que les identifiants d’extensions sont corrects
  3. Assurez-vous que les extensions prennent en charge les conteneurs distants (la plupart le font)

Port déjà utilisé

Erreur : Le port 3000 est déjà alloué

Solutions :

  1. Arrêtez les conteneurs en conflit : docker ps et docker stop <conteneur>
  2. Changez le mappage des ports dans forwardPorts
  3. Utilisez des ports dynamiques : VS Code attribuera automatiquement des ports disponibles

Les modifications du Dockerfile ne sont pas appliquées

Problème : Dockerfile modifié mais les changements ne s’affichent pas

Solution : Reconstruisez sans cache :

Dev Containers: Reconstruire le conteneur sans cache

Le conteneur s’arrête immédiatement

Problème : Le conteneur démarre puis s’arrête

Solution : Ajoutez une commande pour le maintenir en cours d’exécution dans docker-compose.yml :

command: sleep infinity

Ou dans devcontainer.json :

{
  "overrideCommand": true
}

✅ Conclusion

Les Dev Containers dans VS Code apportent cohérence, simplicité et automatisation à votre flux de travail de développement. Ils transforment des configurations complexes et fragiles en environnements définis par le code qui fonctionnent, indépendamment de votre machine ou de votre système d’exploitation.

Points clés :

  • 🎯 Éliminer les problèmes « fonctionne sur ma machine » — Tout le monde utilise des environnements identiques
  • 🚀 Onboarding plus rapide — Les nouveaux membres de l’équipe sont productifs en quelques minutes, pas en jours
  • 🔒 Meilleure sécurité — Isoler les dépendances de votre système hôte
  • 📦 Portabilité — Votre environnement voyage avec votre code
  • 🤝 Consistance d’équipe — Plus de conflits de versions de dépendances
  • 🔄 Parité CI/CD — Utilisez la même image en développement et en intégration continue

Que vous travailliez sur un simple script Python ou une architecture complexe de microservices avec plusieurs bases de données, les Dev Containers offrent une base solide pour le développement moderne.

Si vous travaillez sur des projets multilingues, contribuez à des dépôts open source, onboarding fréquent de nouveaux développeurs ou souhaitez simplement des environnements de développement propres et reproductibles — les Dev Containers sont un outil indispensable dans votre stack.

Commencez petit : essayez les Dev Containers sur votre prochain projet. Une fois que vous aurez expérimenté les avantages, vous vous demanderez comment vous avez pu développer sans eux.

📚 Ressources utiles et articles liés

Documentation officielle :

Articles liés sur ce site :