2. Préliminaires: Docker

Supports complémentaires

La plupart des systèmes étudiés dans ce cours peuvent s’installer et s’exécuter avec l’environnement Docker (http://www.docker.com). Docker permet d’émuler un système distribué de serveurs. Un serveur est une entité qui fournit un service.... Concrètement:

  • un serveur machine est un ordinateur, tournant sous un système d’exploitation, et connecté en permanence au réseau via des ports; un serveur machine est identifiable sur le réseau par son adresse IP.
  • un serveur logiciel est un processus exécuté en tâche de fond d’un serveur machine qui communique avec des clients (logiciels) via un port particulier.
  • un client (logiciel) est un programme qui communique avec un serveur (logiciel);
  • une machine virtuelle est un programme qui simule, sur une machine hôte, un autre ordinateur.

Exemple.

Un serveur web est un processus (Apache par exemple) qui communique sur le port 80 d’un serveur machine. Si ce serveur machine a pour IP 163.12.9.10, alors tout client web (Firefox par exemple) peut s’adresser au serveur web à l’adresse 163.12.9.10:80.

La figure Un exemple de système distribué, avec serveurs virtuels et clients illustre ces concepts de base, que nous utiliserons maintenant intensivement sans plus d’explication.

_images/Serveurs.png

Fig. 2.1 Un exemple de système distribué, avec serveurs virtuels et clients

Avant de donner quelques explications plus élaborées, il vous suffit de considérer que Docker permet d’installer de d’exécuter très facilement, sur votre ordinateur personnel, et avec une consommation de ressources (mémoire et disque) très faible, ce que nous appellerons pour l’instant des “pseudos-serveurs” en attendant d’être plus précis. Docker offre deux très grands avantages.

  • il propose des pseudo-serveurs pré-configurés, prêts à l’emploi, qui s’installent en quelques clics;
  • il est tout aussi facile d’installer plusieurs pseudos-serveurs communiquant les uns avec les autres et d’obtenir donc un système distribué complet, sur un simple portable (doté d’une puissance raisonnable).

Docker permet de transformer un simple ordinateur personnel en data center! Bien entendu, il n’en a pas la puissance mais pour tester et expérimenter, c’est extrêmement pratique.

Installation: Docker existe sous tous les systèmes, dont Windows. Pour Mac OS X et Windows, un installateur Docker-toolbox est fourni à https://www.docker.com/products/docker-toolbox. Sous Linux c’est un peu différent, mais si vous êtes sous Linux c’est probablement que vous savez très bien vous débrouiller.

Je vous encourage à consulter les compléments suivants qui vous seront très utiles, notamment pour les utilisateurs de Windows.

Note

Merci de me signaler des compléments qui seraient utiles à intégrer dans le présent document, pour les environnements différents de Mac OS X, et notamment Windows.

Docker en quelques mots

Essayons de comprendre ce qu’est Docker avant d’aller plus loin. Vous connaissez peut-être déjà la notion de machine virtuelle (VM). Elle consiste à simuler par un composant logiciel, sur une machine physique, un ordinateur auquel on alloue une partie des ressources (mémoire, CPU). Partant d’une machine dotée par exemple de 4 disques et 256 GO de mémoire, on peut créer 4 VMs indépendantes avec chacune 1 disque et 64 GO de RAM. Ces VMs peuvent être totalement différentes les unes des autres. On peut en avoir une sous le système Windows, une autre sous le système Linux, etc.

L’intérêt des VMs est principalement la souplesse et l’optimisation de l’utilisation des ressources matérielles. L’organisation en VMs rend plus facile la réaffectation, le changement du dimensionnement, et améliore le taux d’utilisation des dispositifs physiques (disque, mémoire, réseau, etc.).

Les VMs ont aussi l’inconvénient d’être assez gourmandes en ressource, puisqu’il faut, à chaque fois, faire tourner un système d’exploitation complet, avec tout ce que cela implique, en terme d’emprise mémoire notamment.

Docker propose une solution beaucoup plus légère, basée sur la capacité du système Linux à créer des espaces isolés auxquels on affecte une partie des ressources de la machine-hôte. Ces espaces, ou containers partitionnent en quelque sorte le système-hôte en sous-systèmes étanches, au sein desquels le nommage (des processus, des utilisateurs, des ports réseaux) est purement local. On peut par exemple faire tourner un processus apache sur le port 80 dans le conteneur A, un autre processus apache sur le port 80 dans le conteneur B, sans conflit ni confusion. Tous les nommages sont en quelque sorte interprétés par rapport à un container donné (notion d’espace de nom).

Les conteneurs Linux sont beaucoup plus légers en consommation de ressources que les VMs, puisqu’ils s’exécutent au sein d’un unique système d’exploitation. Docker exploite cette spécificité du système Linux pour proposer un mode de virtualisation (que nous avons appelé “pseudo-serveur” en préambule) léger et flexible.

Docker et ses conteneurs

Docker (ou, très précisément, le docker engine) est un programme qui va nous permettre de créer des conteneurs Linux et d’y installer des environnements prêts à l’emploi, les images. Docker s’exécute toujours dans un environnement Linux, pour les raisons mentionnées ci-dessus. Si vous avez une machine sous Windows ou Mac OS, Docker propose une machine virtuelle Linux ultra-légère au sein de laquelle il s’exécute.

La figure L’architecture Docker, sous différents systèmes d’exploitation montre les deux cas de figure. À gauche, la machine hôte est sous Windows ou Mac OS. Docker (engine) va commencer par lancer une VM Linux, et s’exécuter en tant que programme dans cette VM. Grâce à l’interface de commande du programme Docker, ou son interface graphique kitematic, on pourra alors créer des conteneurs.

À droite, le schéma est lègèrement simplifié car l’hôte est un serveur Linux. On peut alors y exécuter directement le moteur Docker et se ramener à la situation précédente.

_images/schema-docker.png

Fig. 2.2 L’architecture Docker, sous différents systèmes d’exploitation

Un peu de vocabulaire: dans tout ce qui suit,

  • Le système hôte est le système d’exploitation principal gérant votre machine ; c’est par exemple Windows, ou Mac OS.
  • Docker VM désigne le système Linux où Docker s’exécute, qui peut donc être soit directement votre machine si vous êtes sous Linux, soit une VM Linux s’exécutant sur votre machine Windows ou Mac OS.
  • Docker engine ou moteur docker est le programme qui gère les conteneurs; il s’exécute dans la Docker VM.
  • Un conteneur est une partie autonome de la Docker VM, se comportant comme une machine indépendante.
  • Le client Docker est l’utilitaire grâce auquel on transmet au moteur les commandes de gestion de ces conteneurs. Il peut s’agir soit de la ligne de commande (Docker CLI) ou de kitematic.

Les images Docker

Un conteneur Docker peut donc être vu comme un sous-système Linux autonome, mobilisant très peu de ressources car l’essentiel des tâches système est délégué au système Linux dans lequel il est instancié. On dispose donc virtuellement d’un moyen de multiplier à peu de frais des pseudo-machines dans lesquelles on pourait installer “à la main” des logiciels divers et variés.

Docker va un peu plus loin en proposant des installations pré-configurées, empaquetées de manière à pouvoir être placées très facilement dans un conteneur. On les appelle des images. On peut ainsi trouver des images avec pré-configuration de serveurs de données (Oracle, Postgres, MySQL), serveurs Web (Apache, njinx), serveurs NoSQL (mongodb, cassandra), moteurs de recherche (ElasticSearch, Solr). L’installation d’une image se fait très simplement, et soulage considérablement des tâches parfois pénibles d’installation directe.

_images/images-docker.png

Fig. 2.3 Les images docker, constituant un pseudo système distribué

Une image se place dans un conteneur. On peut placer la même image dans plusieurs conteneurs et obtenir ainsi un système distribué. Examinons la figure Les images docker, constituant un pseudo système distribué montrant une configuration complète, avec un système-hôte Windows. Nous avons tous les composants à l’œuvre, essayons de bien comprendre.

  • Le système hôte a créé une VM Docker (donc, une machine virtuelle Linux dans laquelle s’exécute le Docker Engine).
  • Docker a téléchargé (nous verrons comment plus tard) les images de plusieurs systèmes de gestion de données: MySQL, MongoDB (un système NoSQL que nous étudierons), et Solr (un moteur de recherche que nous étudierons également).
  • Ces images ont été instanciées dans des conteneurs A, B et C. L’instanciation consiste à installer l’image dans le conteneur et à l’exécuter. Nous avons donc deux conteneurs avec l’image MySQL, et un troisième avec l’image Solr.

L’ensemble constitue donc un système distribué virtuel, le tout s’exécutant sur la machine-hôte et gérable très facilement grâce aux utilitaires Docker. Nous avons par exemple dans chaque conteneur un serveur MySQL. Maintenant, on peut se connecter à ces serveurs à partir de la machine-hôte avec une application cliente (par exemple phpMyAdmin) et tester le système distribué, ce que nous ferons tout au long du cours.

On peut instancier l’image de MongoDB dans 4 conteneurs et obtenir un cluster MongoDB en quelques minutes. Evidemment, les performances globales ne dépasseront pas celle de l’unique machine hébergeant Docker. Mais pour du développement ou de l’expérimentation, c’est suffisant, et le gain en temps d’installation est considérable.

En résumé: avec Docker, on dispose d’une boîte à outils pour émuler des environnements complexes avec une très grande facilité.

Docker en ligne de commande

Dans ce qui suit, je vais illustrer les commandes avec l’utilitaire CLI en prenant l’exemple de ma machine Mac OS X. Ce ne doit pas être fondamentalement différent sous les autres environnements. Vous préférerez sans doute à juste titre utiliser kitematic, décrit dans la prochaine section, mais avoir un aperçu de commandes transmises par ce dernier est toujours utile pour comprendre ce qui se passe.

Important

A l’heure actuelle Kitematic n’est pas disponible sous Linux

Lancement de la Docker VM (Mac OS, Windows)

Important

Cette section ne s’applique que si vous n’êtes pas déjà sous Linux.

Une fois Docker installé, on dispose d’un programme Docker Terminal qui permet de lancer un machine virtuelle Linux, effectue toute la configuration de Docker, et ouvre une fenêtre terminal permettant d’envoyer des commandes au moteur Docker.

Important

Le programme Docker terminal doit se trouver dans le répertoire d’installation de Docker. Pour les experts, il est possible de créer la machine docker avec des options fines de configuration en entrant la commande:

docker-machine start

Mais ça devient compliqué. Le Docker Terminal fait très bien les choses.

Voici un exemple d’affichage résultant du lancement du terminal.

Creating Machine dev...
Creating VirtualBox VM...
Creating SSH key...
Starting VirtualBox VM...
Starting VM...
To see how to connect Docker to this machine, run: docker-machine env dev
Starting machine dev...
Setting environment variables for machine dev...

                        ##         .
                  ## ## ##        ==
               ## ## ## ## ##    ===
           /~~~~~~~~~~~~~~~~~\___/ ===
       ~~~ {~~ ~~~~ ~~~ ~~~~ ~~~ ~ /  ===- ~~~
           \______ o           __/
             \    \         __/
              \____\_______/

The Docker Quick Start Terminal is configured to use Docker with the “default” VM.

À ce stade, la machine virtuelle Linux intégrant Docker est lancée. On peut communiquer avec elle grâce à l’utilitaire docker-machine. Entrez par exemple la commande suivante:

docker-machine env

Elle affiche les variables d’environnement configurant l’accès à la machine Docker. Vous devriez obtenir une réponse comparable à la suivante:

export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://192.168.99.100:2376"
export DOCKER_CERT_PATH="/Users/philippe/.docker/machine/machines/default"
export DOCKER_MACHINE_NAME="default"
# Run this command to configure your shell:
# eval $(docker-machine env)

Décryptons. Cette réponse nous dit que l’on peut communiquer avec la machine virtuelle à l’adresse tcp://192.168.99.100:2376. Le nom de la machine Docker est default (on pourrait créer plusieurs machines, avec des noms différents) et les fichiers sont placés dans le répertoire .docker/machine/machines/default. Ces paramètres doivent être définis dans des variables d’environnement pour pouvoir communiquer avec la machine Docker. Si vous ouvrez un autre terminal, vous pouvez donc configurer ces variables simplement avec la commande:

eval $(docker-machine env)

La machine Docker est un serveur Linux indépendant et dispose donc d’une adresse IP. On l’obtient de la manière suivante:

docker-machine ip

Cette dernière commande est très importante car l’adresse IP nous permet de nous connecter aux conteneurs gérés par Docker.

Quand vous en avez assez, vous pouvez arrêter la machine docker avec la commande:

docker-machine stop

Notre première image

Maintenant, dans un terminal configuré pour accéder à Docker, vous pouvez installer une image et l’exécuter. Pour communiquer avec le moteur Docker et lui transmettre des commandes, on utilise un programme client nommé simplement docker. L’image la plus simple est un Hello world, on l’instancie avec la commande suivante:

docker run hello-world

Le run est la commande d’instanciation d’une nouvelle image dans un conteneur Docker. Voici ce que vous devriez obtenir à la première exécution.

docker run hello-world

   Unable to find image 'hello-world:latest' locally
   latest: Pulling from library/hello-world
   4276590986f6: Pull complete
   Status: Downloaded newer image for hello-world:latest

   Hello from Docker.

Décryptons à nouveau. La machine Docker a cherché dans son répertoire local pour savoir si l’image hello-world était déjà téléchargée. Ici, comme c’est notre première exécution, ce n’est pas le cas (message Unable to find image locally). Docker va donc télécharger l’image et l’instancier. Le message Hello from Docker. s’affiche: l’utilité est limitée, mais cela montre à toute petite échelle le fonctionnement général: on choisit une image, on applique run et Docker se charge du reste.

Gérer mon conteneur

La liste des images est disponible avec la commande:

docker images

Une image est instanciée dans un conteneur avec la commande run.

docker run --name 'nom-conteneu' <options>

Les options dépendent de l’image: voir les sections suivantes pour des exemples avec MySQL et MongoDB. La liste des conteneurs est disponible avec la commande:

docker ps -a

L’option -a permet de voir tous les conteneurs, quel que soit leur statut (en arrêt, ou en cours d’exécution).

Voici quelques commandes utiles pour gérer un conteneur dont nous allons supposer que le nom est mon-conteneur. Tout d’abord on peut l’arrêter avec la commande stop.

docker stop mon-conteneur

Et le relancer avec la commande start.

docker start mon-conteneur

Pour le supprimer, c’est la commande docker rm (cela permet de libérer le nom mon-conteneur au besoin).

Pour inspecter la configuration système/réseau d’un conteneur, Docker fournit la commande inspect.

docker inspect mon-conteneur

On obtient un large document JSON.

Exercices

Ici, vous devriez faire le point et tenter de vérifier que vous comprenez bien ce qui se passe.

Exercice Ex-S1-1: testons notre compréhension

Savez-vous répondre aux questions suivantes?

  • Qu’est-ce qu’une machine Docker, où se trouve-t-elle, quel est son rôle?
  • À quoi sert le terminal Docker, et qu’est-ce qui caractérise un tel terminal?
  • Qu’est-ce que la machine hôte? Doit-elle forcément tourner sous Linux?
  • Une instance d’image est-elle placée dans un conteneur, dans la machine hôte ou dans la machine Docker?
  • Peut-on instancier une image dans plusieurs conteneurs?

Si vous ne savez pas répondre, cela vaut la peine de relire ce qui précède, ou des ressources complémentaires sur le Web. Vous serez plus à l’aise par la suite si vous avez une idée claire de l’architecture et de ses concepts-clé.

Exercice Ex-S1-2: premiers pas Docker

Maintenant, effectuez les opérations ci-dessus sur votre machine. Installez Docker, lancez le conteneur hello-world, affichez la liste des conteneurs, supprimez le conteneur hello-world.

Installons MySQL

Vous voulez travailler avec MySQL? Nous allons voir comment installer l’image Docker d’un serveur MySQL, sans aucun effort (ou presque).

Choisir une image et l’instancier

La démarche générale pour une installation consiste à cherche l’image qui vous convient sur le site http://hub.docker.com qui donne accès au catalogue des images Docker fournies par la communauté des utilisateurs. La figure Le site d’hébergement des images Docker. montre la page d’accueil du site.

_images/docker-hub.png

Fig. 2.4 Le site d’hébergement des images Docker.

Faites une recherche avec le mot-clé “mysql”. Comme on pouvait s’y attendre, de nombreuses images sont disponibles. La plus standard s’appelle tout simplement mysql (figure Les images de serveurs MySQL.).

_images/docker-mysql.png

Fig. 2.5 Les images de serveurs MySQL.

Choisissez une image, et cliquez sur le bouton Details pour connaître les options d’installation. En prenant l’image standard, on obtient la page de documentation illustrée par la figure Documentation d’installation de l’image mysql

_images/docker-mysql-install.png

Fig. 2.6 Documentation d’installation de l’image mysql

Vous avez deviné ce qui reste à faire. Installez l’image dans un conteneur sur votre machine avec la commande suivante:

docker run --name serveur-mysql -e MYSQL_ALLOW_EMPTY_PASSWORD=yes -d mysql:latest

Vous avez le droit bien sûr de choisir librement le nom de votre serveur, et votre mot de passe. L’option -d indique la version de l’image: prenez latest sauf si vous avez de bonnes raisons de faire autrement. La première fois, l’image doit être téléchargée, ce qui peut prendre un certain temps. Par la suite, le lancement du conteneur instanciant l’image est quasi instantané.

C’est tout! Vous avez installé et lancé un serveur MySQL. Vous pouvez le vérifier avec la commande suivante qui donne la liste des conteneurs en cours d’exécution.

docker ps

Accéder à mon serveur MySQL

Comment accéder à mon serveur MySQL, se connecter, créer des bases de données, etc? Il faut se connecter au serveur MySQL avec un programme spécialisé, ou programme client. Nous allons utiliser le MySQL Workbench qui peut se télécharger ici:: http://dev.mysql.com/downloads/workbench/.

Installez ce programme sur votre machine-hôte et exécutez-le. Vous obtiendrez la fenêtre de la figure Le client MySQLWorkbench.

_images/MySQLWorkbench.png

Fig. 2.7 Le client MySQLWorkbench

Il faut créer une connexion avec le serveur MySQL qui tourne dans notre conteneur serveur-mysql. Ce qui soulève une question délicate: quelle est l’adresse de ce conteneur, et sur quel port peut-on accéder au serveur MySQL? Regardons à nouveau la figure Les images docker, constituant un pseudo système distribué. Pour accéder au serveur MySQL, il faut en principe d’abord aller sur la VM Docker, puis sur le conteneur serveur-mysql, ce qui est un peu compliqué. Le conteneur serveur-mysql lui-même exécute un processus mysqld (le serveur MySQL) qui est en attente sur le port 3306.

Docker fournit un mécanisme pour sauter une étape en associant directement un port sur la machine Docker à un port d’un conteneur. Arrêtez votre conteneur, supprimer-le et récréez-le avec la commande suivante:

docker run --name serveur-mysql -p 6603:3306 -e MYSQL_ALLOW_EMPTY_PASSWORD=yes  -d mysql:latest

L’option -p indique que le port 3306 du conteneur est renvoyé sur le port 6603 de la machine Docker (regardez à nouveau la figure Les images docker, constituant un pseudo système distribué). Comme on peut obtenir l’adresse IP de la machine Docker avec

docker-machine ip

cela signifie qu’on peut se connecter à MySQL à cette adresse IP (par exemple 192.168.99.100), sur la port 6603, avec le compte root/nfe204. C.Q.F.D.: il ne vous reste plus qu’à tester cette connexion dans MySQLBench.

Ouf! Prenez le temps de bien comprendre, car une fois ces mécanismes assimilés, nous serons libérés de tot souci pour créer nos systèmes distribués et les expérimenter par la suite. Et je vous rassure: l’ensemble est géré de manière plus conviviale avec Kitematic (ce qui ne dispense pas de comprendre ce qui se passe).

Exercices

Exercice Ex-S2-1: installez MySQL

À vous de mettre en pratique: vous devez installer une image MySQL, tester la connexion avec MySQLWorkBench, et effectuer les opérations de gestion courante: arrêter/démarrer le conteneur, supprimer le conteneur.

Exercice Ex-S2-1: installez MongoDB

Même exercice, mais cette fois avec MongoDB, un système NoSQL très utilisé. Les principes sont les mêmes: vous récupérez une image de MongoDB, vous l’instanciez, vous configurez le port d’accès, et vous testez l’accès avec un client à partir de la machine-hôte. Un client populaire est RockMongo (http://rockmongo.com).

Kitematic

Kitematic est l’interface graphique de Docker. Elle facilite la gestion des conteneurs et des images et fournit un tableau de bord sur le système distribué virtuel.

_images/kitematic.png

Fig. 2.8 Le client Kitematic

Installer un nouveau conteneur

Il suffit de cliquer sur New: on obtient la liste des images disponibles (l’équivalent de ce qui est proposé sur http://hub.docker.com), avec une fonction de recherche. En cliquant sur une image, elle est tout d’abord téléchargée sur la machine Docker, puis instanciée dans un nouveau conteneur.

_images/kitematic-new.png

Fig. 2.9 Choix d’un nouveau conteneur / image

Un lien mène de chaque image vers le catalogue des images (hub) Docker: il peut être utile de consulter la documentation d’une image pour connaître ses caractéristiques.

Gestion d’un conteneur

En cliquant sur le nom de l’un des conteneurs disponibles, on dispose de toutes les options associées: démarrage (start), arrêt (stop), suppression du conteneur (la croix), accès à l’utilitaire de commandes sur le conteneur (exec), et enfin paramétrages divers (settings).

Un paramètre important est le renvoi du port de l’image instanciée dans le conteneur (par exemple le serveur MySQL) vers un port de la machine Docker. Ce renvoi permet d’accéder avec une application de la machine-hôte à l’instance de l’image comme si elle s’exécutait directement dans la machine Docker. Reportez-vous à la section précédente pour des explications complémentaires à ce sujet.

Exercices

Exercice Ex-S3-1: installez MySQL avec Kitematic

Effectuez les opérations d’installation et de gestion de MySQL avec Kitematic.

Exercice Ex-S3-2: installez MongoDB avec Kitematic

Même exercice avec MongoDB.