Une question m’a été posée : « comment développer des applications NetDevOps directement dans des conteneurs ? ». Si la question peut sembler orienter le débat vers des sujets compliqués, il n’en est rien. Il existe une façon très simple de répondre.
Le contexte de la question doit être précisé. Il s’agissait de conteneurs Docker qui tournaient sur une VM Linux Ubuntu 20.04 distante. Les conteneurs étaient lancés avec de la persistance de stockage sur des volumes externes. C’est une bien meilleure pratique que d’utiliser des points de montage dans des répertoires de la VM (Virtual Machine).
Alors que les points de montages dépendent de la structure du répertoire et du système d’exploitation de la machine hôte, les volumes sont entièrement gérés par Docker. Les volumes présentent plusieurs avantages par rapport aux points de montages :
- Les volumes sont plus faciles à sauvegarder ou à migrer que les points de montages sur des répertoires.
- Il est possible de gérer les volumes à l’aide des commandes Docker CLI ou de l’API Docker.
- Les volumes fonctionnent sur les conteneurs Linux et Windows.
- Les volumes peuvent être partagés de manière plus sûre entre plusieurs conteneurs.
- Les drivers de volume permettent de stocker des volumes sur des hôtes distants ou des fournisseurs de cloud, de chiffrer le contenu des volumes ou d’ajouter d’autres fonctionnalités.
- Les nouveaux volumes peuvent avoir leur contenu pré-rempli par un conteneur.
- Les volumes sur Docker Desktop ont des performances bien supérieures à celles des points de montages des hôtes Mac et Windows.
De plus, les volumes sont souvent un meilleur choix que les données directement stockées dans le conteneur, car un volume n’augmente pas la taille des conteneurs qui l’utilisent et le contenu du volume existe en dehors du cycle de vie d’un conteneur donné.
Pour reproduire la question sous forme d’une expérimentation, il convient de lancer une VM Linux Ubuntu 20.04 sur VMWare (Fusion sur MAC dans le cas démontré ici). Sur cette VM, Docker est installé facilement à l’aide des commandes suivantes :
sudo apt install apt-transport-https ca-certificates curl software-properties-common curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable" sudo apt install docker-ce sudo usermod -aG docker ${USER}
Pour démontrer le fonctionnement, l’utilisation d’une simple image nginx suffit à mettre en place le contexte nécessaire. Les commandes Docker sont lancées à la main pour analyser chaque étape, mais un fichier compose pourrait automatiser tout ceci.
Pour créer un volume persistant, la commande docker volume create nginx-vol
est utilisée. Pour analyser où Docker a enregistré ce volume, la commande suivante donne les informations : docker volume inspect nginx-vol
.
On peut constater que le volume Docker a été stocké dans /var/lib/docker/volumes
. Pour lancer un conteneur nginx qui utilise le volume afin de stocker ses fichiers html, la commande suivante est utilisée : docker run -d --name=nginxtest -p 80:80 -v nginx-vol:/usr/share/nginx/html nginx:latest
.
Si on regarde le contenu du volume externe au conteneur, on peut constater que les fichiers qu’utilise le conteneur nginx dans /usr/share/nginx/html
sont en fait présents dans le volume.
L’idée n’est pas d’aller directement travailler dans ce volume car, outre le fait que ce n’est pas une bonne pratique, on se confronterait à des problèmes de droits d’accès en permanence. Chaque fois qu’on interviendra dans le répertoire /usr/share/nginx/html
du conteneur, c’est en fait dans le volume persistant que les données seront enregistrées.
Pour le prouver, il convient de commencer à mettre en place la connexion avec Visual Studio Code. Le plugin « Remote Development » continent tous les outils nécessaires. La fonction « Remote-SSH » permet dans un premier temps de se connecter sur la VM qui porte Docker. Ensuite, la fonction « Remote-Containers » permet de visualiser les conteneurs qui sont lancés sur la VM et de se connecter au conteneur nommé nginxtest
. L’ouverture du répertoire /usr/share/nginx/html
affiche les deux fichiers html disponibles.
Une simple modification dans le titre <h1>
de la page d’accueil va permettre de mettre en évidence le fonctionnement.
Si on vérifie le fichier index.html qui est stocké dans le volume Docker externe, on peut constater que la modification est bien enregistrée.
Si on détruit le conteneur et qu’on le recrée avec le même volume externe, il retrouvera la donnée telle qu’elle avait été modifiée… CQFD !
Une question complémentaire pourrait se poser : « comment précharger des fichiers sur le conteneur avant même de commencer à développer avec Visual Studio Code ? ».
La méthode la plus répandue consiste à recréer une image dérivée de l’image de base en rajoutant les fichiers désirés. Voici un exemple simple avec l’image nginx sur laquelle on charge un fichier index.html
différent de celui d’origine.
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Bootstrap demo</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" crossorigin="anonymous"> </head> <body> <h1>Hello, world!</h1> <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/js/bootstrap.bundle.min.js" integrity="sha384-pprn3073KE6tl6bjs2QrFaJGz5/SUsLqktiwsUTF55Jfv3qYSDhgCecCxMW52nD2" crossorigin="anonymous"></script> </body> </html>
FROM nginx:latest COPY ./index.html /usr/share/nginx/html/index.html
Le fichier Dockerfile est exécuté avec la commande : docker build -t mynginx .
et la nouvelle image ainsi créée est lancée avec la commandé précédente légèrement modifiée : docker run -d --name=nginxtest -p 80:80 -v nginx-vol:/usr/share/nginx/html mynginx:latest
.
Il faut noter que dans la mesure où un des rôles du volume est d’offrir de la persistance de la donnée, si le volume existe déjà avec un fichier index.html
, ce dernier sera prioritaire sur celui embarqué dans le conteneur.
La deuxième méthode, très simple et rapide, consiste à utiliser le cli de Docker : docker cp index.html nginxtest:/usr/share/nginx/html
et le fichier est copié dans le volume nginx-vol
au travers du conteneur.
Si vous essayez de reproduire la même expérience avec Docker Desktop sur MAC, ne cherchez pas le volume sur le File System de votre MAC. Il faut savoir que Docker Desktop fait tourner les conteneurs dans une VM, c’est donc dans cette VM que sont stockés les volumes.