{{indexmenu_n>19}}
# C'est quoi Docker ?
Il y plein d'introductions et tutoriels sur Internet, alors on va se limiter à donner une intuition des concepts utilisés dans le reste du wiki. :-D
## Rappels sur machines virtuelles vs conteneurs
Docker est un logiciel libre permettant d'**isoler** des applications dans des **conteneurs**.
C'est quoi un conteneur ?
Un conteneur peut être vu comme une sorte de machine virtuelle légère.
Qu'est ce qu'une machine virtuelle ?
C'est la simulation d'une machine physique. Ainsi, sur une même machine physique, plusieurs machines virtuelles peuvent tourner simultanément et indépendamment.
Chaque machine virtuelle a l'impression d'être seule, avec son matériel propre (disques, CPU, RAM), son système d'exploitation, et ses applications.
En pratique, ce qui fait l'interface entre la machine physique et les machines virtuelles est un logiciel qui se nomme **hyperviseur**. L'hyperviseur est chargé de simuler le matériel utilisé par les machines virtuelles, par exemple.
L'intérêt d'une machine virtuelle est donc :
* De pouvoir **allouer** les ressources d'une machine physique de manière flexible
* De pouvoir **isoler** les machines entre elles (sécurité, performance...)
On peut représenter les machines virtuelles comme suit :
{{ :technique:docker:general:vm_schema.png |}}
Les conteneurs reprennent un peu le même principe, mais pour les applications. En réalité, il n'y a pas un système d'exploitation complet qui tourne dans chaque machine, et le matériel n'est pas simulé.
En particulier, le noyau du système d'exploitation utilisé par chaque conteneur est le même, et c'est celui de la machine hôte.
Un conteneur est donc une boîte auto-suffisante, isolée, contenant une application, pouvant s'exécuter n'importe où.
Docker est tout simplement un gestionnaire de conteneurs. Il y en a d'autres, comme Podman.
En comparaison avec une machine virtuelle :
{{ :technique:docker:general:container_schema.png |}}
## Pourquoi Docker ?
Historiquement, c'est Docker qui a fait exploser la popularité des conteneurs, parce qu'il fournit :
* Un outil en ligne de commande permettant de gérer facilement le cycle de vie des conteneurs
* Un espace permettant de partager ses applications conteneurisées avec les autres (le Docker Hub)
* Tout un écosystème permettant de faire de la haute disponibilité, de la répartition de charge, etc.
Ce qu'il faut retenir, c'est qu'un conteneur permet de lancer une application isolée des autres applications, par rapport à un système Linux basique, où toutes les applications écrivent dans les mêmes dossiers (`/etc`...) et peuvent communiquer les unes avec les autres par défaut.
Un des avantages est qu'un « même » conteneur pourra tourner sur n'importe quelle machine, dans des environnements très différents.
## Concepts fondamentaux de Docker
### Philosophie
La philosophie de Docker rejoint celle des micro-services : créer des briques ré-utilisables, qui font une chose et le font bien, et qui sont capables de communiquer avec d'autres briques. Cette approche s'oppose à celle dite **monolithique**.
La brique, dans ce cas, est un conteneur.
En suivant cette philosophie, pour un service et sa base de données, on créera **deux conteneurs différents**, de sorte qu'on puisse facilement changer de base de données sans devoir manipuler complètement le conteneur applicatif.
### Image Docker
Une **image** Docker peut être vue comme une grosse archive inerte, qui contient tout ce qu'il faut pour lancer une application. L'intérêt principal d'une image est qu'elle est **utilisable sur n'importe quel système d'exploitation** et **réutilisable**.
Pour faire une analogie, pour installer un paquet sur une distribution Linux, les commandes vont varier (`apt-get`, `pacman`, `yum`...), tout comme le nom des paquets. La configuration distribuée sera différente, l'emplacement des fichiers aussi. Avec Docker, il suffit d'une seule commande pour lancer une application sur n'importe quel système d'exploitation et obtenir le même résultat **partout**.
Une image Docker se construit à partir d'un fichier nommé `Dockerfile`, qui est en quelque sorte la **recette de cuisine de l'image**.
Les images peuvent hériter d'autres images.
En continuant la métaphore, ça reviendrait à dire : *pour préparer une sauce au poivre, partez d'un roux, puis [...].*
Plus concrètement, un `Dockerfile` pourrait ressembler à ceci :
```
FROM debian:buster
RUN apt-get install wget
COPY code /code
EXPOSE 8000
CMD [ "/code/app" ]
```
`FROM debian:buster`\\
\\
`debian` est le nom de l'image et `buster` est son **tag**. Le tag est une déclinaison de l'image, et est souvent utilisé en tant que version.
`RUN apt-get install wget`\\
\\
On installe `wget` dans l'image.
`COPY code /code`\\
\\
On copie le dossier `code`, situé sur la machine, dans l'image, à l'emplacement `/code`.
`EXPOSE 8000`\\
\\
L'image pourra écouter sur le port 8000.
`CMD [ "/code/app" ]`\\
\\
La commande à exécuter pour démarrer l'application est `/code/app`
On dit que l'on **construit** une image **à partir** d'un `Dockerfile`. Une fois l'image construite, on peut lui donner un nom et un tag, par exemple `app:v1`.
Une commande typique pour construire cette image serait :
```bash
# Construire l'image avec le Dockerfile
# et les fichiers du dossier courant
docker build -t app:v1 .
```
Dans notre micro exemple, on obtient une image redistribuable, qui contient `wget`, est prête à écouter sur le port 8000, a le code de l'application et sait quoi exécuter. On peut donc la lancer de n'importe où : elle s'auto-suffit.
### Conteneur Docker
Un conteneur Docker est une instance d'une image Docker. C'est sa version vivante.
En d'autres termes, plusieurs conteneurs peuvent être instanciés depuis **la même image** et vivre leur vie indépendamment. Ce principe de réutilisation est très utile.
Exemple : on prépare une image `nginx`, qui permet de lancer un site web. On a cinq sites web. On lance 5 conteneurs à partir de cette image, sans avoir à se taper cinq fois la configuration.
Lorsqu'un conteneur est éteint puis supprimé, toutes les modifications apportées par rapport à l'image de base sont supprimées également. C'est pourquoi il est utile d'utiliser les **volumes**, qui stockent de manière persistante les modifications à certains fichiers du conteneur (contenu d'une base de donnée, etc). On voit ça [[technique:tech_team:tuto_docker|dans la page sur la fabrication d'image Docker]] !