Aller au contenu

Utilisation des DevContainer

Mise à jour :

logo visual studio code

Découvrons ensemble comment mettre en place un environnement de développement complet pour une application en exploitant les Devcontainers de Visual Studio Code.

L’un des défis majeurs en développement est de s’assurer que l’environnement local soit identique pour tous les membres d’une équipe, afin d’éviter les problèmes liés à des configurations différentes. Les Devcontainers, qui s’appuient sur Docker, permettent de créer un environnement de développement isolé et réplicable, garantissant que tout le monde travaille dans les mêmes conditions.

Dans ce guide, nous allons créer un projet Astro, configurer un Devcontainer pour automatiser l’environnement, et voir comment exploiter ces outils pour un flux de travail optimisé et cohérent, sans polluer notre système local.

Pourquoi utiliser Devcontainers avec VSCode ?

Les Devcontainers sont un concept introduit par Microsoft dans le cadre du développement de l’extension Remote - Containers pour Visual Studio Code. Ils permettent de créer des environnements de développement basés sur Docker, encapsulant l’ensemble des dépendances, configurations et outils nécessaires pour travailler sur un projet donné.

L’idée derrière les Devcontainers est de résoudre un problème fréquent chez les développeurs : la variabilité des environnements de développement. Les différences de versions de logiciels, de systèmes d’exploitation ou de dépendances peuvent entraîner des bugs difficiles à reproduire et à résoudre.

Avec les Devcontainers, tout ce dont ton projet a besoin (comme la version de Node.js, de python, les outils de compilation ou les bibliothèques spécifiques) est défini dans un fichier de configuration, permettant de garantir un environnement identique pour chaque développeur, indépendamment de son système d’exploitation ou de sa machine.

L’origine des Devcontainers remonte à la montée en popularité des containers grâce à Docker. Les containers sont des environnements légers, portables et isolés, capables d’exécuter des applications de manière reproductible. Microsoft a exploité cette technologie pour l’intégrer directement dans VSCode, facilitant ainsi la configuration et la gestion de ces containers pour le développement. Le concept de Devcontainers repose donc sur l’utilisation d’un fichier devcontainer.json, qui définit l’environnement Docker à utiliser, ainsi que les extensions, paramètres de l’éditeur et scripts à exécuter après le démarrage du container.

Un autre avantage majeur des Devcontainers est leur portabilité. En incluant le fichier de configuration dans ton projet (par exemple via Git), tout membre de ton équipe peut cloner le dépôt et ouvrir le projet dans VSCode avec exactement le même environnement de développement, y compris les mêmes versions de dépendances et les mêmes configurations d’outils. Cela permet d’éviter les fameux “ça marche sur ma machine”, car tous les développeurs travaillent dans un environnement identique.

Installation de Devcontainer

Avant de commencer à utiliser les Devcontainers avec VSCode, il est nécessaire de s’assurer que ton environnement est prêt et correctement configuré. Voici ce dont on a besoin pour démarrer.

Visual Studio Code

VSCode est l’éditeur de code dans lequel nous allons configurer et utiliser les Devcontainers. Il est disponible sur les principales plateformes, et on peux le télécharger à partir du site officiel : VSCode - Télécharger.

Docker

L’élément clé des Devcontainers repose sur l’utilisation d’un moteur de container (ici Docker) pour gérer l’environnement isolé.Docker est une plateforme qui permet de créer et d’exécuter des containers – des environnements légers et portables qui encapsulent tout ce dont ton projet a besoin, y compris les dépendances, les configurations et le système d’exploitation.

Extension Remote - Containers

Une fois Docker configuré installe l’extension Remote - Containers dans VSCode. Cette extension permet d’ouvrir ton projet dans un container Docker défini par un fichier devcontainer.json, ce qui permet de reproduire l’environnement exact sur n’importe quelle machine.

Terminal window
# Installation de l'extension via la marketplace de VSCode
# Commande dans le terminal de VSCode
code --install-extension ms-vscode-remote.remote-containers

Comment fonctionne un Devcontainer dans VSCode

Un Devcontainer est un environnement de développement isolé qui fonctionne à l’intérieur d’un container Docker. Il est conçu pour garantir que tous les développeurs travaillent dans un environnement identique, avec les mêmes dépendances, outils et configurations. Ce système assure une portabilité et une réplicabilité totales, ce qui est crucial lorsque l’on travaille sur des projets collaboratifs ou sur des environnements complexes.

Communication entre VSCode et le Container

Lorsqu’on configure un Devcontainer, VSCode se connecte à une version serveur de lui-même, appelée VSCode Server, qui est exécutée à l’intérieur du container. La configuration globale est la suivante :

  • VSCode côté local : Sur la machine hôte (local OS), on continue d’utiliser l’interface graphique de VSCode. Les extensions de l’interface utilisateur (comme les thèmes, l’UI de l’éditeur, etc.) sont gérées localement. Cela signifie que l’expérience utilisateur reste fluide et qu’on peut interagir avec l’éditeur comme d’habitude.

  • VSCode Server dans le container : À l’intérieur du container Docker, VSCode exécute une instance de VSCode Server qui est responsable de gérer les fichiers source et les outils associés (debugger, terminal, système de fichiers, extensions spécifiques au projet). Tout ce qui est lié au projet (comme les extensions de langage ou de compilation) est exécuté dans cet environnement isolé.

Synchronisation et gestion des fichiers

Le code source de ton projet est généralement stocké sur ta machine locale, mais il est monté dans le container à l’aide d’un volume partagé (Volume Mount). Ce système de montage assure que toutes les modifications apportées au code source sont immédiatement reflétées dans le container, et inversement.

Cela signifie qu’on n’a pas à copier manuellement les fichiers dans le container ou à se soucier de la synchronisation. Dès qu’on modifie un fichier dans VSCode, cette modification est instantanément disponible dans l’environnement isolé du container. Cela est particulièrement utile lors du développement avec des frameworks où les fichiers sont souvent recompilés à la volée.

Redirection de ports

L’un des grands avantages des Devcontainers est leur capacité à gérer des services réseau. Par exemple, si ton projet Node.js exécute un serveur sur le port 4321, ce serveur sera exécuté à l’intérieur du container. Cependant, grâce à la fonctionnalité de redirection de ports (exposed port), ce serveur sera accessible sur ta machine locale via http://localhost:4321.

Le fichier devcontainer.json permet de configurer facilement quels ports seront exposés ou redirigés. Cette redirection automatique de ports permet aux développeurs de tester leur application dans un environnement proche de la production tout en interagissant avec lui via leur système local.

Terminal et processus d’exécution

Dès que l’on ouvre un terminal, il est possible de taper des commandes. Par exemple, lorsqu’on lance la commande npm run dev pour démarrer un serveur de développement d’une application nodejs, cette commande s’exécute à l’intérieur du container. Cela garantit que toutes les dépendances et les outils, y compris Node.js ou npm, sont isolés dans cet environnement, sans affecter le système hôte.

Debugging et extension dans le container

Les extensions de workspace sont des extensions spécifiques au projet qui sont exécutées à l’intérieur du container. Par exemple, des extensions pour le formatage du code, la vérification syntaxique (comme ESLint), ou la gestion des dépendances de langage (comme TypeScript ou Prettier) sont installées et exécutées directement dans le container. Cela garantit que tous les développeurs du projet utilisent les mêmes versions des outils.

VSCode permet également le débogage dans le container. On peut utiliser le débogueur intégré pour mettre des breakpoints, inspecter les variables et suivre l’exécution du code, comme si on travaillait localement. L’intégration entre VSCode et le Devcontainer permet de suivre l’exécution des processus dans un environnement isolé tout en utilisant l’interface de VSCode.

Créer un fichier Devcontainer

Dans cette section, je vais expliquer en détail comment configurer le fichier devcontainer.json pour un projet Astro. Ce fichier est au cœur de la configuration de votre Devcontainer, car il définit l’environnement Docker utilisé par VS Code pour exécuter votre projet. Voici les étapes pour créer un fichier devcontainer.json adapté à un projet Astro.

Emplacement du fichier devcontainer.json

Le fichier devcontainer.json doit être placé dans un dossier appelé .devcontainer à la racine de votre projet. Pour cela, vous pouvez exécuter la commande suivante dans le terminal :

Terminal window
mkdir .devcontainer

Ensuite, créez le fichier devcontainer.json dans ce dossier :

Terminal window
code .devcontainer/devcontainer.json

Contenu du fichier devcontainer.json

Voici un exemple de fichier devcontainer.json pour un projet Astro :

{
"name": "Astro Dev Container",
"image": "node:20-apline3.19",
"postCreateCommand": "npm install",
"customizations": {
"vscode": {
"extensions": ["astro-build.astro-vscode"]
}
},
"forwardPorts": [4321],
}

Décomposons ce fichier pour comprendre chaque élément :

L’attribut "name" donne un nom à votre Devcontainer. Ici, il est simplement appelé “Astro Dev Container”, mais vous pouvez choisir n’importe quel nom.

L’attribut "image" définit l’image Docker à utiliser pour l’environnement. Dans ce cas, nous utilisons l’image node:20-apline3.19, qui inclut node:20-apline3.19, une version compatible avec Astro.

L’attribut "postCreateCommand" permet de spécifier une commande qui sera exécutée automatiquement après la création du Devcontainer. Ici, nous utilisons cette option pour exécuter npm install, ce qui installe toutes les dépendances du projet à partir du fichier package.json. Cela garantit que tous les modules nécessaires sont prêts à l’emploi dès que le container est lancé.

L’attribut "forwardPorts" est utilisé pour exposer un port du container Docker vers votre machine hôte. Dans le cadre d’un projet Astro, le serveur de développement fonctionne généralement sur le port 4321. Cette ligne permet de rediriger ce port pour que vous puissiez accéder à l’application en local à l’adresse http://localhost:4321.

Si vous avez besoin d’exposer plusieurs ports (par exemple, si vous ajoutez un service de base de données), vous pouvez les ajouter dans cette section. Par exemple, pour exposer également le port 5432 d’une base de données PostgreSQL :

{
"forwardPorts": [4321, 5432]
}

Vous pouvez également configurer d’autres aspects de l’environnement de développement avec le fichier devcontainer.json. Par exemple, vous pouvez ajouter des variables d’environnement, spécifier des commandes de démarrage, ou configurer des scripts personnalisés. Voici comment ajouter une variable d’environnement pour indiquer que vous êtes en mode développement :

{
"env": {
"NODE_ENV": "development"
}
}

La section "customizations" permet de configurer VS Code et d’installer automatiquement certaines extensions lorsque vous ouvrez le projet dans un Devcontainer. Dans notre exemple, nous ajoutons l’extension Astro pour VS Code (astro-build.astro-vscode), qui offre des fonctionnalités spécifiques pour travailler avec ce framework, telles que le surlignage syntaxique et l’autocomplétion.

Si vous avez besoin d’autres extensions, comme ESLint ou Prettier, vous pouvez les ajouter ici. Voici un exemple avec ces deux extensions supplémentaires :

"customizations": {
"vscode": {
"extensions": [
"astro-build.astro-vscode",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode"
]
}
}

Pour obtenir la liste de vos extensions :

Terminal window
code --list-extensions
akamud.vscode-theme-onedark
astro-build.astro-vscode
davidanson.vscode-markdownlint
esbenp.prettier-vscode
github.vscode-github-actions
github.vscode-pull-request-github
gitlab.gitlab-workflow
hashicorp.hcl
hashicorp.terraform
ms-python.black-formatter
ms-python.debugpy
ms-python.python
ms-python.vscode-pylance
ms-toolsai.datawrangler
ms-toolsai.jupyter
ms-toolsai.jupyter-keymap
ms-toolsai.jupyter-renderers
ms-vscode-remote.remote-containers
ms-vscode-remote.remote-ssh
ms-vscode-remote.remote-ssh-edit
ms-vscode-remote.vscode-remote-extensionpack
ms-vscode.remote-explorer
ms-vscode.remote-server
outscale.osc-viewer
redhat.ansible
redhat.fabric8-analytics
redhat.vscode-xml
redhat.vscode-yaml

Cela peut être utile si vous avez besoin de configurer des paramètres spécifiques pour le développement, comme activer un mode de débogage dans votre application Astro.

Une fois le fichier devcontainer.json terminé, vous pouvez démarrer votre Devcontainer en ouvrant le projet dans VS Code et en choisissant l’option Rouvir dans le conteneur. Cela lancera Docker, créera le container avec l’image spécifiée, installera les dépendances et configurera l’environnement de développement.

Vous serez alors prêt à commencer à développer votre site Astro dans un environnement isolé, avec toutes les bonnes configurations déjà en place.

Docker Compose

Dans certains cas, votre site Astro pourrait nécessiter des services supplémentaires, tels qu’une base de données, un serveur d’API ou d’autres composants liés. Grâce à Docker Compose, il est possible d’orchestrer plusieurs services dans un environnement isolé et de les intégrer facilement dans votre Devcontainer.

Pour ajouter une base de données PostgreSQL à votre projet Astro, commencez par créer un fichier docker-compose.yml à la racine de votre projet. Ce fichier contiendra les définitions des différents services à exécuter, tels que le serveur de développement Astro et le service de base de données.

Voici un exemple de fichier docker-compose.yml avec deux services : web (pour le site Astro) et db (pour la base de données PostgreSQL) :

services:
web:
image: node:20-alpine3.19
ports:
- "4321:4321"
volumes:
- ./:/workspace:cached
command: sleep infinity
db:
image: postgres:14
restart: unless-stopped
volumes:
- postgres-data:/var/lib/postgresql/data
environment:
POSTGRES_USER: astro_user
POSTGRES_PASSWORD: astro_password
POSTGRES_DB: astro_db
ports:
- "5432:5432"
volumes:
postgres-data:

Maintenant qu’on a un fichier docker-compose.yml configuré, il est nécessaire d’ajuster le fichier devcontainer.json pour intégrer ces services dans notre Devcontainer. On doit indiquer à VS Code d’utiliser Docker Compose au lieu d’une simple image Docker.

Voici un exemple de fichier devcontainer.json modifié pour inclure Docker Compose :

{
"name": "Astro 0.1.1",
"dockerComposeFile": "../docker-compose.yml",
"workspaceFolder": "/workspace",
"service": "web",
"postCreateCommand": "npm install && npm run dev -- --host",
"customizations": {
"vscode": {
"forwardPorts": [
4321
],
"settings": {
"remote": {
"restoreForwardedPorts": true,
"localPortHost": "0.0.0.0"
}
}
}
}
}
  • dockerComposeFile : Ce paramètre indique à VS Code d’utiliser le fichier docker-compose.yml pour lancer les services.
  • service : Ici, le service principal défini est web, qui correspond à votre application Astro. Ce service sera celui utilisé comme environnement principal pour le développement.
  • workspaceFolder : Définit le dossier de travail dans le container, qui est monté depuis votre machine locale.
  • forwardPorts : Expose le port 4321 pour permettre de visualiser le site en développement.
  • customizations : Ajout de l’extension VS Code Docker pour aider à gérer les containers Docker directement depuis l’éditeur.

Une fois les fichiers docker-compose.yml et devcontainer.json prêts, vous pouvez lancer votre environnement de développement avec VS Code. L’éditeur utilisera Docker Compose pour démarrer à la fois votre serveur web et la base de données PostgreSQL.

Ouvrez le projet dans VS Code, puis sélectionnez Rouvrir dans le Conteneur. Cela lancera tous les services définis dans docker-compose.yml, et vous aurez accès à votre site Astro sur http://localhost:4321, ainsi qu’à la base de données sur le port 5432.

Conclusion

Les Devcontainers améliorent clairement la collaboration au sein des équipes de développement en garantissant que chaque membre travaille dans un environnement identique, quelle que soit la machine ou le système d’exploitation utilisé. Un nouveau développeur peut démarrer instantanément sans avoir à configurer un environnement complexe.

De plus, leur portabilité ouvre des possibilités au-delà du développement local. Ils peuvent être utilisés dans des environnements de test automatisé, sur des serveurs de staging, ou encore dans des environnements éphémères créés à la demande dans le cloud. Cela assure une plus grande fiabilité lors du passage de la phase de développement à celle de déploiement.

Dans un pipeline CI/CD, la cohérence de l’environnement est cruciale pour s’assurer que le code fonctionne de manière identique dans toutes les phases, de la phase de développement jusqu’à la production. Avec un Devcontainer, cet environnement est défini une fois pour toutes dans un fichier devcontainer.json, et peut ensuite être réutilisé à chaque étape du pipeline.

Par exemple, dans un pipeline GitHub Actions, vous pouvez configurer un job CI pour exécuter les tests et les validations dans un container basé sur la même image Docker définie dans votre Devcontainer. Cela permet d’éviter les problèmes dus à des différences entre l’environnement local des développeurs et l’infrastructure du pipeline.