Docker utilise une architecture de type client/serveur. Le daemon de docker (dockerd) et docker client sont 2 binaires différents. Cela signifie qu'avec le client docker nous pouvons nous connecter à différents daemon docker.
- Le client communique avec le daemon docker
- Docker daemon sert à :
- Build
- Run
- Distribuer/Répartir les containers docker
Le daemon docker et le client docker communiquent via une API REST. Les requêtes peuvent être faites de 2 manières différentes :
- Sockets UNIX
- Interface réseau
Le daemon docker (dockerd) va :
- Ecouter les requêtes APIs et gérer les différents objets docker (Images/containers/réseaux/volumes)
Le client docker (docker) va :
- permettre à l'utilisateur d'intéragir avec dockerd
- Un registry docker est comme un repo github mais pour les images docker.
- Par défaut le registry est le "docker hub"
- On peut lancer notre propre registre docker (grâce à image registry par exemple)
(source : Docker)
Fonctionnement si nous n'avons pas l'image sur notre hôte :
- On lance un container redis via la commande docker run
- L'image redis n'est pas disponible sur notre hote, on va donc récupérer l'image sur le docker hub.
- Une fois l'image récupérée (celle-ci est stockée sur notre hôte) on va pouvoir lancer le container redis.
Fonctionnement si on possède déjà l'image :
- On lance un container ubuntu via la commande docker run
- L'image ubuntu est présente sur notre hote. On va donc éxécuter le container sans passer par le registry
On peut récupérer une image via la commande docker pull. Si je veux récupérer la dernière version d'ubuntu : docker pull ubuntu:latest
Les images :
- Un template en lecture seul possédant des instructions pour créer un container docker
- Les images sont basés sur d'autres images (nginx-alpine est par exemple basé sur la distribution légère "alpine")
- On peut créer notre propre image (grâce à la commande docker build et les instructions d'un fichier dockerfile)
Les containers :
- Instance exécutable d'une image (start/stop/rm...)
- Connecter un container à un réseau
- Attacher un volume (stockage)
- Créer une image basé sur le container actuel (non recommandé)
- Isolé des autres containers et de l'hôte
Les services :
- Scale des containers à travers de multiple daemon docker
- Plusieurs docker daemon qui tournent ensemble : Docker Swarm
- Définir un état, exemple : je veux 3 replicas de nginx
- Les services possèdent un load balancer natif
Docker Swarm :
- Multiple daemon docker interconnectés entre eux avec différents rôles : Master et Worker
- Les daemon communiquent entre eux grâce à l'API REST
- Supporté à partir de Docker >1.12 (release le 28/07/2016)
Les composants majeurs :
- Client Docker
- Daemon Docker
- containerd
- runc
Les composants travaillent ensemble pour créer et faire tourner des containers :
(source : Blog Docker)
containerd :
- Gère la vie d'un container : start/stop/pause/delete
runc :
- Implémentation du "OCI container-runtime-spec". runc est un outil CLI pour la création et l'exécution de conteneurs selon la spécification OCI.
- Outil CLI léger qui permet l'intégration de libcontainer :
- cgroups : limitation des resources
- namespaces : permet l'isolation entre l'hote et le container
- capabilities : permet l'ajout ou la suppression de droit dans un container. CHOWN par exemple est une capabilities
shim :
- Implémentation de container sans daemon
- containerd crée une instance de runc pour chaque container
- Il permet à runc de se stopper après le démarrage du conteneur.
- le process shim devient le container parent. Cela va permettre de ne pas lancer 100 instances de runc si on a 100 containers (celà serait trop gourmand).
- shim est responsable de :
- Laisser STDIN et STDOUT ouvert. Cela signifie que si dockerd redémarre, cela ne va pas terminer les containers tournant sur ce daemon docker.
- Signaler le status d'exit d'un container à dockerd
docker container run -it --name <NAME> <IMAGE>:<TAG>
Créer un container va se faire via la CLI.
- Le client docker va utiliser la bonne API pour faire exécuter la commande au daemon docker.
- Suite à ça, dockerd va recevoir l'instruction
- Dockerd va appeler containerd pour démarrer le container.
- Dockerd utilise gRPC (CRUD API, soit une Create/Read/Update/Delete API)
- Containerd crée un bundle OCI à partir de l'image docker
- Containerd demande à runc de créer un container en utilisant le bundle OCI crée auparavant
- Runc va s'interfacer avec le kernel de notre hôte afin d'obtenir les éléments nécessaire à la création de ce container (inclus : cgroups, namespaces... vu plus haut)
- Le process du container est considéré comme un "child process"
- Une fois que le container a démarré runc va s'arrêter et shim va le remplacer.
- Ce qui complète le process de lancement d'un container. Celui-ci est maintenant fonctionnel.
Images Docker :
- Un container utilise une image pour être crée
- Chaque image comprend plusieurs "couche" (layer).
- "Build time constructs" tandis que les containers sont "Runtime constructs" : une fois le container exécuté, il est dépendant de l'image. L'image ne peut être supprimée sans que le container ne le soit.
- Les images sont construits grâce à un fichier dockerfile. Un dockerfile est une suite d'instructions (FROM / RUN / ENV / CMD...)
- Les images sont construites en plusieurs layers. Chaque layer correspondent à une instruction du dockerfile.
- Chaque layer sont en lecture seul SAUF le dernier.
- Chaque layer est uniquement la différence entre le layer précédent et le layer actuel.
- Les conteneurs ajoutent une nouvelle couche inscriptible au-dessus des couches sous-jacentes.
- Tous les changements fait dans un container en fonctionnement sont fait sur la couche container. Les changements ne sont pas faits sur l'image.
(source : acloudguru)
Docker hub est l'endroit ou l'on trouve toutes les images docker :
- Registry publique
- Fourni par Docker
- Permet la création de repositories (privée ou publique). Un repo privée gratuit par compte.
- Permet la création de Teams et d'organisations
- Des images officielles sont disponibles sur le Docker Hub
Vous pouvez accéder au docker hub via ce lien : https://hub.docker.com/