0% ont trouvé ce document utile (0 vote)
117 vues413 pages

Introduction à Docker en 5 jours

Transféré par

Shamir Lesabel
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
117 vues413 pages

Introduction à Docker en 5 jours

Transféré par

Shamir Lesabel
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats PDF, TXT ou lisez en ligne sur Scribd

Docker - 5 jours

Maxence Cuingnet 1
Plan

1 - Introduction à Docker
Les “quick wins” avec Docker
Les containers Linux
Les composants de base: namespaces et control groups
Historique de la plateforme
Les composants de l’écosystème : Docker Machine, Docker Compose, Docker Swarm...

2 - Premiers pas avec Docker


Installer sur son environnement (Linux / MacOS / Windows)
Le docker daemon et l’architecture client/serveur
Les commandes de base pour la gestion du cycle de vie d’un container
Supervision et debugging des containers

2
Plan

3 - Les images Docker


Union filesystem et Copy-On-Write
Création manuelle d’une nouvelle image
Création à partir d’un Dockerfile
Bonnes pratiques et performances (cache, écriture du dockerfile, images de base,
arborescence recommandée, etc.)
Partage et utilisation des images (registre Docker)

4 - Les registres d’images


Utilisation
Les registres Docker et autres registres de l’écosystème
Docker Hub / Docker registry / Docker Trusted Registry

3
Plan

5 - La persistance des données avec Docker


Données non persistées par défaut
La notion de volume
Définition dans le Dockerfile ou à l'exécution
Bind-mount : montage d’un répertoire de l’hôte dans un container

6 -Mettre en œuvre une application multi-conteneurs


Le format de fichier défini par Docker Compose
Gérer l’interconnexion de plusieurs conteneurs avec Docker Compose
Le binaire docker-compose
La notion de service
Communication entre les différents services
Modification du nombre d’instances d’un service

4
Plan

7 - Intégration continue avec GitLab CI et Registry


Considérations préliminaires
Mise en place du système
Gestion de la persistance

8 - Orchestration avec Docker Swarm


Présentation de Docker Swarm (node, service, stack, config, secret)
Les rôles manager et worker
Algorithme de consensus distribué Raft : réplication des logs et quorum
Le routing mesh
Les ports utilisés dans un swarm
Des outils de Monitoring (Prometheus et Grafana)
Montage d’un cluster Swarm

5
Plan

9 - Administration des conteneurs au quotidien


Cycle de vie d’un conteneur
Analyse des logs
Le réseau dans Docker (standard, bridge, liens entre conteneurs, le réseau « physique », etc.)
Les volumes Docker

10 - Docker Machine
Présentation
Déploiement et utilisation d’hôtes Docker en local
Déploiement et utilisation d’hôtes Docker sur un cloud provider (AWS, DigitalOcean)

6
Plan

11 - Stockage
Utilisation et cas d’usage
File storage vs Block storage vs Object storage
Présentation de REX-Ray pour l’orchestration du stockage

12 - Sécurité
Les éléments de sécurité avec Docker
Isolation (namespaces) et limitation des ressources (cgroups)
Linux Security Modules
Capabilities / Seccomp
Scan de vulnérabilités
Content Trust
La sécurité dans un swarm

7
Plan

13 - Monitoring
Gestion des logs
Exemple d’utilisation de Prometheus
Exemple d’utilisation de ELK

14 - Docker Entreprise
Présentation
Exemple de mise en place sur DigitalOcean
Démo de l’interface

15 - Des projets de l’écosystème Docker


Revue de différents projets développés autour de Docker

8
1 - Introduction à Docker

Qu’est-ce qu’un container ?

➔ Partie isolée du système


➔ Différence avec les VM ⇒ Ils partagent beaucoup de ressources avec
le système hôte (kernel) et VM ⇒ système complet indépendant
➔ Plus léger à lancer et à utiliser
➔ Software isolé

9
1 - Introduction à Docker

➔ Les containers ne sont pas exclusifs à Docker et peuvent être utilisés


sans
➔ Brevet depuis 1956 par Malcom McLean
➔ Besoin grandissant d’embarquer différents packages avec différentes
contraintes

10
1 - Introduction à Docker

11
1 - Introduction à Docker

➔ Virtualisation : VMs sont isolées, toutes les ressources (CPU, stockage,


réseau..) sont livrées par l’hyperviseur
➔ Donc installation d’un kernel supplémentaire (très lourd) et d’un OS
complet
➔ Souci : dégradation de performances
➔ demande beaucoup de ressources matérielles
➔ démarrage long

12
1 - Introduction à Docker

13
1 - Introduction à Docker
➔ Containerisation : les ressources sont virtualisées
➔ pas d’OS supplémentaire qui consomme des ressources importantes
➔ Utilise l’OS hôte, son kernel et les librairies nécessaires
➔ Héberge des apps sans se soucier des dépendances, des librairies et
des binaires
➔ Performance native
➔ Isolation du process
➔ Ne contient en général que ce qui lui est nécessaire comme packages
et apps
➔ Peut être détruit, répliqué, coupé, relancé… rapidement

14
1 - Introduction à Docker

15
1 - Introduction à Docker
➔ Suite d’outils pour configurer, lancer et gérer des containers
➔ Commande principale : docker
➔ Contenu de la suite : docker-compose pour rapidement démarrer et
stopper une configuration de plusieurs containers
➔ Software Container → Pas un nouveau concept mais Docker l’a rendu
plus rapide, facile à utiliser
➔ Docker permet de définir des images, puis lancement de containers
avec ces images

16
1 - Introduction à Docker
➔ Suite d’outils pour configurer, lancer et gérer des containers
➔ Commande principale : docker
➔ Contenu de la suite : docker-compose pour rapidement démarrer et
stopper une configuration de plusieurs containers
➔ Software Container → Pas un nouveau concept mais Docker l’a rendu
plus rapide, facile à utiliser
➔ Docker permet de définir des images, puis lancement de containers
avec ces images

17
INTRODUCTION : Docker

➔ VmWare, Hyper-V, KVM utilisent un hyperviseur


➔ L’avantage est que Docker utilise directement le kernel de l’OS
➔ Images → Sorte de containers pre-built (comparable à des snapshots
pour les VM)
➔ N’importe qui peut faire une image et la partager, plus besoin de build
➔ Les images peut être améliorées et recevoir des fonctionnalités supp.

18
INTRODUCTION : Docker

➔ Docker : open-source
➔ permet le packaging d’applications en containers
➔ But : développer des app, les transporter et les lancer
➔ Compartimente totalement les app, lancement très rapide
➔ Gestion simple et rapide identique à un management d’applications
➔ Réduction du temps de développement, duplication rapide d’environnements

19
INTRODUCTION : Docker

➔ Possibilité d’exploiter plusieurs OS : des OS différents exploitent des containers


qui pourront communiquer entre eux
➔ En moyenne, réduction de 50% des besoins en hardware
➔ Donc très utilisé dans les Clouds
➔ Également avantage de portabilité → Même comportement de l’app en
container quelque soit l’OS, la VM ou le cloud.
➔ Autre motivation → la sécurité : chaque container est isolé de l’autre. Si une app
est compromise, il est beaucoup plus difficile de “contaminer” les autres

20
INTRODUCTION : Docker

➔ Docker peut scanner le contenu des applications et alerter sur les failles de
sécurité dans le stack
➔ Possibilité de signer des packages et de demander à Docker de ne lancer que
les containers contenant les auteurs de confiance
➔ Docker contient des composants open-source et est livré sous Docker
Community Edition (Docker CE) et Docker Enterprise Edition (Docker EE)
➔ Docker CE est gratuit et a des mises à jour mensuelles
➔ Docker Enterprise a une inscription payante : plus de fonctionnalités et versions
tous les trimestres→ Support 24/7 et sécurité ++

21
INTRODUCTION : Docker

➔ Ils utilisent la même


plateforme donc possibilité
de lancer les apps
identiquement sur les deux

22
INTRODUCTION : Docker

➔ Docker peut également upload que les deltas entre une version actuelle et une
nouvelle
➔ Énorme librairie open-source d’images -> Succès de Docker
➔ Docker Inc. affiche plus de 100 milliards de téléchargements de container
➔ Très utilisé en workflows CI/CD
➔ Scaling très rapide et facile
➔ Permet des environnements à haute densité

23
INTRODUCTION : Docker

➔ Docker CLI et Engine permettent de définir des réseaux isolés pour les
containers, sans toucher un seul routeur
➔ Utilisation de fichiers de configuration
➔ Avantage sécuritaire
➔ Réseau privé virtuel → contrôle aisé
➔ Développement des architectures de microservices

24
INTRODUCTION : Docker

25
INTRODUCTION : Docker

● DockerFile → simple fichier texte contenant des instructions pour builder une
image de container. DockerFile permet d’automatiser le build. C’est Docker
Engine qui va lancer cela
● Image Docker → contient les exécutables du code source ainsi que les outils,
les librairies, les dépendances dont l’app a besoin. Possibilité de construire une
image totalement mais souvent chargement depuis des repos.
● Images Docker formées de couches : chaque couche correspond à une version.
Les couches précédentes sont exploitables par la suite.

26
INTRODUCTION : Docker
● Un container Docker est une instance en fonctionnement de l’image.
● Les images ne sont que des fichiers en lecture seule
● Un container est complètement isolé, il faut lui indiquer s’il doit communiquer
ou s’il doit utiliser un volume extérieur
● Docker Hub → Repo public d’images. Contient plus de 100,000 images fournies
par des dev indépendants, des projets open-source ou des sociétés, ou même
par Docker Inc.
● Présence aussi d’images certifiées (sont dans le Docker Trusted Registry)

27
INTRODUCTION : Docker

● Si peu de container → possibilité de gérer avec Docker Engine lui-même


● Mais si bcp de containers (centaines, milliers) → besoin d’outils →orchestrateur
● Docker Engine est une application client-serveur
● Le serveur est un process daemon (commande dockerd)
● API REST → interface de communication avec le daemon
● CLI client qui utilise cette API REST pour contrôler le daemon Docker

28
INTRODUCTION : Docker

● Docker Compose → Permet la gestion de plusieurs containers qui résident tous


dans le même hôte
● Utilisation d’un fichier YAML → quels services sont exploités, quels sont les
liens entre les containers, lancement avec une commande

29
INTRODUCTION : Docker
● Docker Compose : définit des volumes pour le stockage (documents, données,
dépendances…)
● Le Composer manage tout le build et lance tout le projet
● C’est le niveau suivant → Orchestration de containers
● Services : Load Balancing, Allocation de ressources, scaling up, fermer des
instances...

30
INTRODUCTION : Docker

● Kubernetes → Pour monitorer, exploiter des containers dans des


environnements complexes
● Open Source, lancé par Google
● Calendriers d’action , architectures, déploiements, mises à jour, découvertes,
load balancing, monitoring et plus…
● Conforme à O.C.I. https://opencontainers.org/

31
INTRODUCTION : Docker

Docker a été créé pour les besoins d'une société de


Platform as a Service (PaaS) appelée DotCloud
En mars 2013, l'entreprise a créé une nouvelle structure
nommée Docker Inc
Son produit Docker est open source

32
1 - Introduction à Docker
Les containers Linux

➔ Cependant, la technologie “container” existaient déjà avant Docker (proposé


en 2013 au public)
➔ En 2008 : LXC → Linux Containers : point de départ du développement de
Docker.
➔ Les containers LXC étaient souvent liés à la configuration de l’hôte, les
containers Docker se lancent sans modifications nécessaires quelque soit
l’hôte. https://linuxcontainers.org/

33
1 - Introduction à Docker
Les containers Linux

➔ Les conteneurs lxc peuvent toutefois héberger plusieurs process dans un seul
container
➔ Docker : un seul process dans un container
➔ lxc → une app tourne pendant qu’une autre est off ou en update ou en
“réparation”
➔ Docker peut automatiquement builder une image à partir d’un code source
➔ Docker peut suivre les mises à jour d’une image, retourner à une précédente
version, savoir qui a builder telle version et comment.

34
1 - Introduction à Docker
Les containers Linux : lxc

LXC repose sur les fonctionnalités des cgroups du noyau Linux disponibles depuis
sa version 2.6.24. Il repose également sur d'autres fonctionnalités de cloisonnement
comme le cloisonnement des espaces de nommage du noyau, permettant d'éviter à
un système de connaître les ressources utilisées par le système hôte ou un autre
conteneur.

35
1 - Introduction à Docker
Les composants de base : namespaces et control groups

36
1 - Introduction à Docker
Les composants de base : namespaces et control groups
Les Cgroups :Google utilisait les conteneurs Linux avant même que Docker n’existe. De plus, Google exécute
tout dans un conteneur. Selon les estimations, Google démarre 2 milliards de conteneurs par semaine.

Les fonctionnalités du noyau Linux sous-jacentes utilisées par Docker sont les cgroups (groupes de contrôle)
et les espaces de noms. En 2008, les cgroups ont été introduits dans le noyau Linux sur la base du travail
précédemment effectué par les développeurs Google. Ils limitent et tiennent compte de l’utilisation des
ressources d’un ensemble de processus du système d’exploitation.

Le noyau Linux utilise un espace de noms pour isoler les ressources système des processus les unes par
rapport aux autres. Le premier espace de noms, c’est-à-dire l’espace de noms de montage, a vu le jour en
2002

37
1 - Introduction à Docker
Les composants de base : namespaces et control groups
L'un des buts de la conception de cgroups a été de fournir une interface unifiée à différents cas d'utilisation, en allant du contrôle
de simples processus (comme nice) à la virtualisation au niveau du système d'exploitation (comme OpenVZ, Linux-VServer, LXC).
Cgroups fournit :
● Limitation des ressources : des groupes peuvent être mis en place afin de ne pas dépasser une limite de mémoire —
cela inclut aussi le cache du système de fichier . L'article original a été présenté au Linux Symposium et s'intitule
Containers: Challenges with the memory resource controller and its performance en Juillet 2007
● Priorisation : certains groupes peuvent obtenir une plus grande part de ressources processeur 5 ou de bande passante
d'entrée-sortie
● Comptabilité : permet de mesurer la quantité de ressources consommées par certains systèmes en vue de leur
facturation par exemple7.
● Isolation : séparation par espace de nommage pour les groupes, afin qu'ils ne puissent pas voir les processus des
autres, leurs connexions réseaux ou leurs fichiers
● figer les groupes ou créer un point de sauvegarde et redémarrer

38
1 - Introduction à Docker
Les composants de base : namespaces et control groups

39
1 - Introduction à Docker
Les composants de base : namespaces et control groups

40
1 - Introduction à Docker
Les composants de base : overlay filesystems

41
1 - Introduction à Docker
Les composants de base : overlay filesystems

Présentation de aufs : AuFS (Advanced multi layered Unification FileSystem or


AnotherUnionFS) est un service du système de fichiers de Linux dérivé de
Unionfs, qui permet de fusionner plusieurs points de montage appelés «
branches » : c'est un union mount.

Sous Linux, le service Docker prend en charge plusieurs pilotes de stockage de


couche d'image différentes dont aufs.

https://docs.docker.com/engine/reference/commandline/dockerd/#daemon-sto
rage-driver

42
1 - Introduction à Docker

Apports de Docker : Docker Engine pour créer et gérer des conteneurs Dockers.

LXC a été créé pour être un « conteneur de système» et non une « conteneur
d’applications». Le système conteneur est comme une VM, mais léger, utilisant le
même noyau pour toutes les VM. Ces machines virtuelles ont leurs propres
services system-v ou systemd, comme toute autre solution de machine virtuelle.

Docker est un conteneur d'applications, les images ont le minimum requis pour
exécuter une seule application.

43
1 - Introduction à Docker
La principale raison était la prise en charge native de GO Lang. À l'époque, le démon
Docker s'exécutait sur la ligne de commande lxc, ce qui causait des problèmes
lorsque des erreurs se produisaient. L'écrire nativement avec GO dans libcontainer
l'a rendu plus supportable et moins sujet aux erreurs.

Finalement, libcontainer avec un programme wrapper appelé runc a été donné à


l'Open Container Initiative comme implémentation par défaut de la spécification
d'exécution OCI.

Désormais, Docker s'exécute par défaut sur runc, comme presque tous les autres
moteurs de conteneurs tels que CRI-O, Podman et Buildah. Runc crée ensuite le
conteneur.
44
1 - Introduction à Docker
Les composants de l’écosystème : Dockerfile

45
1 - Introduction à Docker
Les composants de l’écosystème : Docker Compose

46
1 - Introduction à Docker
Les composants de l’écosystème : Docker Swarm

47
1 - Introduction à Docker
Les composants de l’écosystème : Docker Hub

48
1 - Introduction à Docker
Les composants de l’écosystème : Docker Desktop

49
2 - Premiers pas avec Docker

Installer sur Linux

https://docs.docker.com/engine/install/ubuntu/

Installer sur MacOs

https://docs.docker.com/desktop/mac/install/

50
2 - Premiers pas avec Docker
Installer sur Windows

Décocher la case , nous utiliserons


Hyper-V

51
2 - Premiers pas avec Docker

Patienter pendant
l’installation puis redémarrer
le poste

52
2 - Premiers pas avec Docker

Cliquer sur Use Hyper-V

53
2 - Premiers pas avec Docker

Cliquer sur not now


54
2 - Premiers pas avec Docker

Petit tutoriel de
présentation facultatif
mais très instructif

55
2 - Premiers pas avec Docker

Pour démarrer votre premier


conteneur Docker :

56
2 - Premiers pas avec Docker

docker run -it ubuntu bash

Nom de l’image
Rend le conteneur interactif
avec notre ligne de commande,
comme si on était dans le
conteneur Argument supplémentaire qui
stipule qu’on lance l’application
bash dans ubuntu

57
2 - Premiers pas avec Docker

Le docker daemon et
l’architecture
client/serveur

58
2 - Premiers pas avec Docker

Le docker daemon et
l’architecture
client/serveur

59
2 - Premiers pas avec Docker

Le docker daemon et
l’architecture
client/serveur

60
2 - Premiers pas avec Docker

Le docker daemon et
l’architecture
client/serveur

61
2 - Premiers pas avec Docker

Le docker daemon et
l’architecture
client/serveur

62
2 - Premiers pas avec Docker

Pourquoi lancer des app


dans containers ?

63
2 - Premiers pas avec Docker

64
2 - Premiers pas avec Docker

65
2 - Premiers pas avec Docker

66
2 - Premiers pas
avec Docker

67
2 - Premiers pas
avec Docker

68
2 - Premiers pas avec Docker

Commandes de base

docker run hello-world

docker search ubuntu

docker pull ubuntu

69
2 - Premiers pas avec Docker
Commandes de base
docker [option] [command] [arguments]

docker info

docker pull <nom_image>

https://hub.docker.com/_/e7e5dbc4-2103-4b7c-9409-b0ca32ce3d83

70
2 - Premiers pas avec Docker

docker run -d --name <nom_container> <nom_image>

docker run -i -t <nom_image> /bin/bash

docker stop <container-id> (ou <container_name>) (ou kill)

docker start <container-id> (ou <container_name>)

71
2 - Premiers pas avec Docker

docker ps Liste les containers actifs

docker ps -a Liste tous les containers ∀ états

docker rm <nom_container> Supprimer container

docker rm -f $(sudo docker ps -a -q)

72
2 - Premiers pas avec Docker

docker rmi $(docker images -q) Effacer les images

docker system prune Liste tous les containers ∀ états

73
2 - Premiers pas avec Docker

Pour lister les process d’un container docker top <nom container>

Pour exécuter des commandes dans un container docker exec <nom_container> ls /

docker exec -i -t 023828e786e0 /bin/bash

docker exec 023828e786e0 apt-get install apache2 -y

74
2 - Premiers pas avec Docker

Pour lister les ports utilisés par un container : docker port <nom_container>

Pour lister les ports utilisés par un container :

docker inspect IMAGE_ID OR CONTAINER_ID

Pour lister les logs : docker logs <Container ID>

75
2 - Premiers pas avec Docker
docker inspect [OPTIONS] NAME|ID [NAME|ID...]

docker container inspect [OPTIONS] CONTAINER [CONTAINER...]

docker inspect 023828e786e0

docker inspect --format='{{range


.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $DOCKER_CONTAINER_NAME

docker inspect --format='{{range $p, $conf := .NetworkSettings.Ports}}


{{$p}} -> {{(index $conf 0).HostPort}} {{end}}' $DOCKER_INSTANCE_NAME

76
2 - Premiers pas avec Docker

Copier des dossiers depuis l’hôte vers le container

docker cp ./directory_path 023828e786e0:/home/ubuntu

Et inversement

docker cp 023828e786e0:/etc/apache2/sites-enabled .

77
2 - Premiers pas avec Docker
Debugging des containers
docker stats [OPTIONS] [CONTAINER...]
plusieurs commandes de bases docker logs [OPTIONS] CONTAINER
docker top [OPTIONS] CONTAINER [ps OPTIONS]
docker exec -it CONTAINER [OPTIONS]

78
2 - Premiers pas avec Docker
Debugging des containers : entrer dans un container

docker exec -it container_id bash

docker exec -it container_id /bin/sh

docker exec container_id ls -la

le flag -u permet de spécifier un user uid=1013 et gid=1053.

docker exec -it -u 1013:1023 container_id ls -la

79
2 - Premiers pas avec Docker
L'uid et le gid n'ont pas besoin d'exister dans le conteneur, mais la commande peut entraîner des
erreurs. Si vous souhaitez lancer un conteneur et entrer immédiatement à l'intérieur afin de vérifier
quelque chose, vous pouvez faire :

docker run...; docker exec -it $(docker ps -lq) bash

la commande docker ps -lq génère uniquement l'ID du dernier conteneur (le l dans -lq) démarré. (cela
suppose que vous avez bash comme interprète disponible dans votre conteneur, vous pouvez avoir sh
ou zsh ou tout autre)

80
2 - Premiers pas avec Docker
Monitorer l’usage des ressources

L'inspection de l'utilisation des ressources système est un moyen efficace de détecter les applications qui
se comportent mal. Cet exemple est l'équivalent de la commande top traditionnelle pour les conteneurs :

docker stats

Pour suivre les statistiques de conteneurs spécifiques, listez-les sur la ligne de commande :

docker stats 7786807d8084 7786807d8085

81
2 - Premiers pas avec Docker
Par défaut, docker stats affiche l'ID des conteneurs, ce qui n'est pas très utile, si vous préférez afficher les
noms du conteneur, faites simplement

docker stats $(docker ps --format '{{.Names}}')

L'inspection de l'utilisation des ressources système est un moyen efficace de résoudre un problème sur une
application en cours d'exécution. Cet exemple est l'équivalent de la commande ps traditionnelle pour les
conteneurs.

docker top 7786807d8084

82
2 - Premiers pas avec Docker
Pour filtrer le format de la sortie, ajoutez des options ps sur la ligne de commande :

docker top 7786807d8084 faux

Ou, pour obtenir la liste des processus exécutés en tant que root, ce qui est une pratique potentiellement dangereuse :

docker top 7786807d8084 -u root

La commande docker top s'avère particulièrement utile lors du dépannage de conteneurs minimalistes sans shell ni
commande ps

83
2 - Premiers pas avec Docker
« Attacher à un conteneur » consiste à démarrer une session de terminal dans le contexte dans lequel le conteneur (et tous les
programmes qu'il contient) est en cours d'exécution. Ceci est principalement utilisé à des fins de débogage, mais peut
également être nécessaire si des données spécifiques doivent être transmises aux programmes exécutés dans le conteneur.

La commande attach est utilisée pour ce faire. Il a cette syntaxe :

docker attach <container>

<container> peut être soit l'ID du conteneur, soit le nom du conteneur. Remarque : Attach ne permet qu'une seule session shell
d'être attachée à un conteneur à la fois.

Attention : toutes les saisies au clavier seront transmises au conteneur. Frapper Ctrl-c va tuer votre conteneur.

Pour détacher d'un conteneur attaché, appuyez successivement sur Ctrl-p puis Ctrl-q

Pour attacher plusieurs sessions shell à un conteneur, ou simplement comme alternative, vous pouvez utiliser exec.
84
2 - Premiers pas avec Docker
exec exécutera un programme dans un conteneur, dans ce cas /bin/bash(un shell, probablement celui du conteneur). -i
indique une session interactive, tandis -t qu'alloue un pseudo-TTY.

Remarque : contrairement à attach , appuyer sur Ctrl-cne terminera la commande exec que lors de l'exécution interactive.

85
2 - Premiers pas avec Docker
Suivre les journaux (les logs) est le moyen le moins intrusif de déboguer une application en cours d'exécution. Cet exemple
reproduit le comportement du tail -f some-application.log du conteneur 7786807d8084.

docker logs --follow --tail 10 7786807d8084

86
2 - Premiers pas avec Docker
Cette commande affiche essentiellement la sortie standard du processus conteneur (le processus avec pid 1).

Si vos journaux n'incluent pas nativement l'horodatage, vous pouvez ajouter le drapeau --timestamps.

Il est possible de consulter les logs d'un conteneur arrêté, soit

● démarrer le conteneur défaillant avec docker run ... ; docker logs $(docker ps -lq)
● trouver l'identifiant ou le nom du conteneur avec

docker ps -a

puis

docker logs container-id ou

docker logs containername

car il est possible de consulter les logs d'un conteneur arrêté

87
2 - Premiers pas avec Docker
Docker n'est qu'un moyen sophistiqué d'exécuter un processus, pas une machine virtuelle. Par conséquent, le débogage
d'un processus "dans un conteneur" est également possible "sur l'hôte" en examinant simplement le processus du
conteneur en cours d'exécution en tant qu'utilisateur disposant des autorisations appropriées pour inspecter ces processus
sur l'hôte (par exemple, root). Par exemple, il est possible de répertorier chaque "processus de conteneur" sur l'hôte en
exécutant un simple ps en tant que root :

sudo ps aux

Tous les conteneurs Docker en cours d'exécution seront répertoriés dans la sortie.

Cela peut être utile lors du développement d'applications pour déboguer un processus s'exécutant dans un conteneur. En tant
qu'utilisateur disposant des autorisations appropriées, des utilitaires de débogage typiques peuvent être utilisés sur le
processus de conteneur, tels que strace, ltrace, gdb, etc.

88
2 - Premiers pas avec Docker

docker run -it --security-opt=seccomp:unconfined centos:7 /bin/bash


yum install strace
strace ls

89
2 - Premiers pas avec Docker

90
2 - Premiers pas avec Docker

91
2 - Premiers pas avec Docker

92
2 - Premiers pas avec Docker

93
2 - Premiers pas avec Docker

94
3 - Les images Docker
Persisting Data

95
3 - Les images Docker
Union filesystem

96
3 - Les images Docker

97
3 - Les images Docker

98
3 - Les images Docker

99
3 - Les images Docker

100
3 - Les images Docker
Création à partir d’un Dockerfile

101
3 - Les images Docker
Création à partir d’un Dockerfile

102
3 - Les images Docker
Création à partir d’un Dockerfile

103
3 - Les images Docker
Création à partir d’un Dockerfile

104
3 - Les images Docker
Création à partir d’un Dockerfile

105
3 - Les images Docker : Dockerfile
❏ Instructions exécutées dans le même ordre que dans le Dockerfile
❏ Commentaires avec #
❏ Instructions :
❏ FROM
❏ COPY : copier des fichiers dans le container
❏ ENV : variables d’environnement
❏ ADD (alternative à COPY)
❏ WORKDIR: met en place un répertoire de travail avec RUN, CMD, ENTRYPOINT, COPY et/ou ADD
❏ EXPOSE : port sur le(s)quel(s) le container écoute
❏ VOLUME : créer un point de montage
❏ USER : pour lancer RUN, CMD et/ou ENTRYPOINT

106
3 - Les images Docker : Dockerfile
❏ Création d’un Dockerfile → Dans un dossier, créer un fichier Dockerfile
❏ Démarrage d’une image de base :
FROM alpine:3.4
RUN apk update
❏ Installation de paquets : RUN apk add vim
RUN apk add curl

❏ Construction de l’image : docker build -t mon_nom/alpine-essai:1.0 .

107
3 - Les images Docker : Dockerfile

❏ Docker a créé une image : docker images

docker run --rm -ti mon_nom/alpine-essai:1.0 /bin/sh

vim --v

curl --version

108
3 - Les images Docker : Dockerfile
❏ Docker a mis en place une étape par commandes du Dockerfile
❏ Une étape = une couche
❏ Docker les enregistre comme images intermédiaires docker images -a
❏ Si le build est relancé sans modification, il sera quasi instantané
❏ Modifions maintenant le Dockerfile :
FROM alpine:3.4

RUN apk update


❏ Puis relancer un build : action
RUN apk add vim
du cache de Docker RUN apk add git

109
3 - Les images Docker : Dockerfile

❏ Modifions maintenant la 2nde étape du build : FROM alpine:3.4

Cela provoque un re-build de RUN apk update


RUN apk add curl
toutes les étapes successives RUN apk add vim
RUN apk add git

110
3 - Les images Docker
Bonnes pratiques : dangling images

111
3 - Les images Docker
Bonnes pratiques : dangling images

112
3 - Les images Docker
Bonnes pratiques : dangling images

113
3 - Les images Docker
Bonnes pratiques : dangling images
Dangling Images → docker images
Notre image est bien disponible mais les images précédentes n’ont ni tag ni nom

Comme elles ne nous servent pas : docker image prune

114
3 - Les images Docker : Dockerfile

Bonnes pratiques :

❏ Minimiser le nombre d’étapes → combiner plusieurs étapes en une seule


ligne
FROM alpine:3.4

En 2 étapes
RUN apk update && \
apk add curl && \
apk add vim && \
apk add git

115
3 - Les images Docker : Dockerfile
Bonnes pratiques :

❏ Possibilité de faire des instructions multi-lignes


FROM alpine:3.4

RUN apk update && apk add \


curl \
git \
vim

116
3 - Les images Docker : Dockerfile
Bonnes pratiques :

❏ Il est conseillé de suivre cet ordre :


a. Installer les outils pour builder l’app
b. installer les dépendances, librairies et packages
c. Builder l’app
❏ Souvent revoir son Dockerfile et toujours garder le minimum d’étapes
❏ Utiliser un fichier .dockerignore :
➢ la commande ‘docker build’ envoie tous les fichier au daemon docker
➢ tous les éléments inutiles au build spécifiés dans ce fichier
➢ taille du contexte de build dans la 1ère ligne de sortie de ‘docker build’

117
3 - Les images Docker : Dockerfile

Bonnes pratiques :

❏ Toujours réfléchir les images Docker qui seront souvent détruites, recréées et/ou
remplacées. Donc tout état est à conservé à l’extérieur des containers
❏ Donner une tâche à un container
❏ Donc ne dédier des containers qu’à une seule zone (database, cache de
mémoire…)
❏ https://docs.docker.com/develop/develop-images/dockerfile_best-practices/

118
3 - Les images Docker : Dockerfile
INSTRUCTIONS (de façon globale) :

❏ https://docs.docker.com/engine/reference/builder/
❏ FROM - chaque Dockerfile commence par FROM, avec l'introduction des
builds multi-étapes à partir de la version 17.05, vous pouvez en avoir
plusieurs instructions FROM dans un seul Dockerfile.
❏ COPY vs ADD - ces deux sont souvent confondus, nous allons plus les
détailler
❏ ENV - définition des variables d’environnement
❏ RUN - exécution des commandes

119
3 - Les images Docker : Dockerfile
INSTRUCTIONS (de façon globale) :

❏ VOLUME - autre source de confusion, quelle est la différence entre


VOLUME de Dockerfile et les volumes de conteneurs ?
❏ USER - quand le root est aussi le gérant
❏ WORKDIR - définit le répertoire de travail
❏ EXPOSE - définit les ports exposés du container
❏ ONBUILD - pour donner plus de flexibilité à votre équipe et à vos clients

120
3 - Les images Docker : Dockerfile
❏ FROM

chaque Dockerfile doit commencer par l’instruction FROM sous forme de FROM
<image>[:tag]. Cela définira l'image de base de votre Dockerfile, ce qui signifie
que les instructions suivantes seront appliquées à cette image de base.

La valeur tag est facultative, si vous ne spécifiez pas le tag, Docker utilisera la
balise latest et essaiera d'utiliser ou d'extraire la dernière version de l'image de
base pendant la construction.

121
3 - Les images Docker : Dockerfile

❏ FROM
● Il y a une instruction que vous pouvez mettre avant FROM dans votre
Dockerfile. Cette instruction est ARG. ARG est utilisé pour spécifier des
arguments pour la commande docker build avec le flag --build-arg
<varname>=<value>.
● Vous pouvez en avoir plusieurs instructions FROM dans votre Dockerfile.
Vous voudrez utiliser cette fonctionnalité, par exemple, lorsque vous utilisez
une image de base pour créer votre application et une autre image de base
pour l'exécuter.
https://docs.docker.com/develop/develop-images/multistage-build/
122
3 - Les images Docker

123
3 - Les images Docker : Dockerfile

❏ FROM

● Donc chaque étape qui commence par FROM s’appelle une étape de build
● Possibilité de nommer chaque étape de build par

FROM <image>[:tag] [AS <name>]

124
3 - Les images Docker : Dockerfile

❏ COPY vs ADD

● Les deux ADD et COPY sont conçus pour ajouter des répertoires et des fichiers à
votre image Docker sous la forme de ADD <src>... <dest> ou COPY
<src>... <dest>. La plupart des ressources suggèrent d'utiliser COPY.
● La raison derrière cela est que ADD a des fonctionnalités supplémentaires par
rapport à COPY qui rendent ADD plus imprévisible et un peu sur-conçu. ADD peut
extraire des fichiers de sources URL, ce qui COPY ne peut pas. ADD peut
également extraire des fichiers compressés en supposant qu'il peut reconnaître et
gérer le format. Vous ne pouvez pas extraire d'archives avec COPY

125
3 - Les images Docker : Dockerfile

❏ COPY vs ADD

● l'instruction ADD était la 1ière sur Docker, et COPY a été ajouté plus tard pour
fournir une solution simple et solide pour copier des fichiers et des répertoires
dans le système de fichiers de votre conteneur.
● Si vous souhaitez extraire des fichiers du Web dans votre image, il est plus sûr
d'utiliser RUN et curl et décompressez vos fichiers avec RUN et les commandes
utilisées en CLI.

126
3 - Les images Docker : Dockerfile
❏ ENV

ENV est utilisé pour définir les variables d'environnement. La chose intéressante à propos
ENV c'est qu'il fait deux choses :

1. Vous pouvez l'utiliser pour définir des variables d'environnement qui seront disponibles
dans votre conteneur. Ainsi, lorsque vous créez une image et démarrez un conteneur
avec cette image, vous constaterez que la variable d'environnement est disponible et
définie sur la valeur que vous avez spécifiée dans le Dockerfile.
2. Vous pouvez utiliser les variables que vous spécifiez par ENV dans le Dockerfile
lui-même. Ainsi, dans les instructions suivantes, la variable d'environnement sera
disponible.

127
3 - Les images Docker : Dockerfile

128
3 - Les images Docker : Dockerfile

129
3 - Les images Docker : Dockerfile

130
3 - Les images Docker : Dockerfile

131
3 - Les images Docker : Dockerfile

132
3 - Les images Docker : Dockerfile

133
3 - Les images Docker : Dockerfile

134
3 - Les images Docker : Dockerfile
❏ RUN

RUN exécutera des commandes, c'est donc l'une des instructions les plus utilisées.

● Beaucoup de commandes type apt-get pour ajouter de nouveaux packages à votre


image. Il est toujours conseillé de mettre les commandes apt-get update et
apt-get install sur la même ligne. Ceci est important en raison de la mise en
cache des couches. Les avoir sur deux lignes distinctes signifierait que si vous ajoutez
un nouveau package à votre liste d'installation, la couche avec apt-get update ne
sera pas invalidé dans le cache de couches et vous pourriez vous retrouver dans un
désordre

135
3 - Les images Docker : Dockerfile
❏ RUN

● RUN a deux formes : RUN <command> (appelée shell form) et RUN ["executable",
"param1", "param2"] appelé exec form.
● RUN <command> invoquera automatiquement un shell ( /bin/sh -c par défaut), tandis
que le formulaire exec n'invoquera pas de commande shell

136
3 - Les images Docker : Dockerfile
❏ VOLUME

● La doc Docker à ce sujet est un peu difficile à suivre


● Vous pouvez utiliser l’instruction VOLUME dans un Dockerfile pour indiquer à Docker
que les éléments que vous stockez dans ce répertoire spécifique doivent être stockés
sur le système de fichiers hôte et non dans le système de fichiers conteneur. Cela
implique que les éléments stockés dans le volume persisteront et seront également
disponibles après la destruction du conteneur.
● il est recommandé de créer un volume pour vos fichiers de données, fichiers de base de
données ou tout fichier ou répertoire que vos utilisateurs modifieront lorsqu'ils
utiliseront votre application

137
3 - Les images Docker : Dockerfile
❏ VOLUME

● Les données stockées dans le volume resteront sur la machine hôte même si vous
arrêtez le conteneur et supprimez le conteneur avec docker rm. (Le volume sera
supprimé à la sortie si vous démarrez le conteneur avec docker run --rm)
● Vous pouvez également partager ces volumes entre conteneurs avec docker run
--volumes-from
● Vous pouvez inspecter vos volumes avec le docker volume ls et docker volume
inspect

138
3 - Les images Docker : Dockerfile
❏ USER
● Évitez de lancer vos fichiers en tant que root, utilisez l’instruction USER pour spécifier
l'utilisateur. Cet utilisateur sera utilisé pour exécuter tout autre instruction RUN, CMD ou
ENDPOINT dans votre Dockerfile.

❏ WORKDIR
● Un moyen très pratique de définir le répertoire de travail, il sera utilisé avec les
instructions RUN, CMD, ENTRYPOINT, COPY et ADD. Vous pouvez spécifier WORKDIR
plusieurs fois dans un Dockerfile.
● Si le répertoire n'existe pas, Docker le créera pour vous.

139
3 - Les images Docker : Dockerfile

❏ EXPOSE
● Une instruction importante pour informer vos utilisateurs des ports qu’écoute votre
application. EXPOSE ne publiera pas le port, vous devrez utiliser docker run -p…
pour le faire lorsque vous démarrez le conteneur.

140
3 - Les images Docker : Dockerfile

❏ CMD et ENTRYPOINT
● CMD est l'instruction pour spécifier quel composant doit être exécuté par votre image
avec des arguments sous la forme suivante : CMD [“executable”, “param1”, “param2”…].
● Vous pouvez remplacer CMD lorsque vous démarrez votre conteneur en spécifiant
votre commande après le nom de l'image comme ceci :

$ docker run [OPTIONS] IMAGE[:TAG] [COMMAND] [ARG...]

● Un seul CMD exploité dans un Dockerfile (vous pouvez en spécifier plusieurs, mais seul
le dernier sera utilisé).

141
3 - Les images Docker : Dockerfile

❏ CMD et ENTRYPOINT
● Il est de bonne pratique de spécifier un CMD même si vous développez un conteneur
générique, dans ce cas un shell interactif est une bonne entrée CMD. Par exemple
CMD ["python"] ou CMD [“php”, “-a”] pour donner à vos utilisateurs quelque
chose avec quoi travailler.
● Alors quel est le problème avec ENTRYPOINT? Lorsque vous spécifiez un point d'entrée,
votre image fonctionnera un peu différemment. Utiliser ENTRYPOINT comme
exécutable principal de votre image. Dans ce cas, tout ce que vous spécifiez dans CMD
sera ajouté à ENTRYPOINT comme paramètres.
ENTRYPOINT ["git"]
CMD ["--help"]

142
3 - Les images Docker : Dockerfile

❏ CMD
● CMD peut s’écrire sous deux syntaxes :

Exec form: CMD ["executable", "parameter1", "parameter2"]


Shell form: CMD command parameter1 parameter2

143
3 - Les images Docker : Dockerfile

❏ LES 3 INSTRUCTIONS
● RUN : Principalement utilisé pour créer des images et installer des applications et des
packages. Crée une nouvelle couche sur une image existante en validant les résultats.
● CMD : Définit les paramètres par défaut qui peuvent être remplacés à partir de
l'interface de ligne de commande (CLI) Docker lorsqu'un conteneur est en cours
d'exécution.
● ENTRYPOINT : Paramètres par défaut qui ne peuvent pas être remplacés lorsque les
conteneurs Docker s'exécutent avec des paramètres CLI.

144
3 - Les images Docker : Dockerfile

❏ ONBUILD
● Très pratique : spécifier des instructions avec ONBUILD qui seront exécutées lorsque
votre image sera utilisée comme image de base d'un autre Dockerfile
● Ceci est utile lorsque vous souhaitez créer une image de base générique à utiliser dans
différentes variantes par de nombreux Dockerfiles, ou dans de nombreux projets ou par
de nombreuses parties.
● Vous n'avez donc pas besoin d'ajouter les éléments spécifiques immédiatement,
comme vous n'avez pas besoin de copier le code source ou les fichiers de
configuration dans l'image de base

145
3 - Les images Docker : Dockerfile

❏ ONBUILD
● Syntaxe : ONBUILD COPY . /usr/src/app
ONBUILD RUN /usr/src/app/mybuild.sh

● Les instructions ONBUILD seront exécutées juste après l’instruction FROM dans le
Dockerfile “enfant”

146
3 - Comment écrire un Dockerfile ? 4 étapes

❏ 1 - Choisir la bonne image de base


Tester les images de base disponibles en ligne pour la technologie en question. Vérifier
généralement différents types, comme une image basée sur Debian Jessie et une autre
basée sur Alpine.

Consulter également les images réalisées par d'autres pour une technologie spécifique. Pour
node.js, par exemple, il est plus conseillé d’utiliser les images de nœud officielles comme
image de base.

147
3 - Comment écrire un Dockerfile ? 4 étapes

❏ 2 - Construire l’environnement dans le shell

Approche d’essai et d’échec : démarrage du container en mode interactif


avec un shell

Exécution manuelle des étapes du Dockerfile et tests → si OK, ajoutée au


Dockerfile

148
3 - Comment écrire un Dockerfile ? 4 étapes

❏ 3 - Ajouter les étapes au Dockerfile et créer l’image


Continuer d'ajouter des étapes en continu au fur et à mesure de la progression dans la
configuration dans le conteneur.

De temps en temps, s’arrêter et construire l’image à partir du Dockerfile pour s'assurer


qu'elle produit les mêmes résultats à chaque fois.

Ensuite, utiliser l'image nouvellement créée pour démarrer un conteneur avec un shell et
poursuivre les étapes d'installation et de configuration.

❏ 4 - Répétez les étapes 2 et 3

149
3 - Création d’un Dockerfile avec CMD

CMD spécifie le programme par défaut qui s'exécutera une fois le conteneur exécuté.

Un point rapide à noter : les commandes CMD ne seront utilisées que lorsque les arguments
de la ligne de commande sont manquants. Voici notre Dockerfile que nous appelons Monde :

FROM centos:7
RUN yum update -y
RUN yum -y install python
COPY ./opt/source code
CMD ["echo", "Hello, Monde"]

150
3 - Création d’un Dockerfile avec CMD

La commande ci-dessous fait deux choses :

● Demande au démon Docker de créer une image


● Définit le nom de la balise sur Monde situé dans le répertoire actuel

$ docker build -t monde .

151
3 - Création d’un Dockerfile avec CMD

Lancement du container : $ docker run Monde

Nous avons exclut un argument de ligne de commande, le conteneur exécute l'instruction CMD
par défaut et affiche Hello, Monde en sortie.

Si nous ajoutons un argument avec la commande run , il remplace l'instruction par défaut, c'est-
à-dire :
$ docker run Monde hostname
Lorsqu'une commande par défaut de CMD est remplacée, la commande ci-dessus exécutera le
conteneur et affichera le nom d'hôte, ignorant ainsi l'instruction echo dans le Dockerfile avec la
sortie suivante :
65fg46d5fg6d84g
152
3 - Création d’un Dockerfile avec CMD

La meilleure façon d'utiliser une instruction CMD est de spécifier des programmes par défaut
qui doivent s'exécuter lorsque les utilisateurs n'entrent pas d'arguments dans la ligne de
commande.

Cette instruction garantit que le conteneur est en cours d'exécution en démarrant une
application dès que l'image du conteneur est exécutée. Ce faisant, l'argument CMD charge
l'image de base dès que le conteneur démarre.

De plus, dans des cas d'utilisation spécifiques, une commande docker run peut être exécutée
via une CLI pour remplacer les instructions spécifiées dans le Dockerfile.

153
3 - Création d’un Dockerfile avec ENTRYPOINT

Une instruction ENTRYPOINT est utilisée pour définir des exécutables qui s'exécuteront
toujours lorsque le conteneur est lancé.

Contrairement aux CMD, les commandes ENTRYPOINT ne peuvent pas être ignorées ou
remplacées, même lorsque le conteneur s'exécute avec des arguments de ligne de commande
indiqués.

Une instruction ENTRYPOINT peut être écrite sous les formes shell et exec :

Exec form: ENTRYPOINT ["executable", "parameter1", "parameter2"]


Shell form: ENTRYPOINT command parameter1 parameter2

154
3 - Création d’un Dockerfile avec ENTRYPOINT

FROM centos:7
RUN yum update -y
RUN yum -y install python
ENTRYPOINT ["echo", "Hello, Monde"]

$ docker run Monde hostname


$ docker build -t Monde .
Hello, Monde hostname

155
3 - Création d’un Dockerfile avec ENTRYPOINT
et CMD
Un cas d'association de ces instructions consiste à automatiser les tâches de démarrage des
conteneurs. Dans un tel cas, l'instruction ENTRYPOINT peut être utilisée pour définir
l'exécutable tout en utilisant CMD pour définir les paramètres.

FROM centos:7
RUN yum update -y
$ docker build -t Monde .
RUN yum -y install python
ENTRYPOINT ["echo", "Hello"]
$ docker run Monde User_JDMonde
CMD ["Monde"]

156
3 - Création d’un Dockerfile avec ENTRYPOINT
et CMD

En règle générale :

● Instructions ENTRYPOINT lors de la création d'une image Docker pour les exécutables toujours
nécessaires.
● Instructions CMD idéales pour un ensemble supplémentaire d'arguments qui agissent comme
des instructions par défaut jusqu'à ce qu'il y ait une utilisation explicite de la ligne de commande
lors de l'exécution d'un conteneur Docker.Une image de conteneur nécessite différents éléments,
notamment des instructions d'exécution, des outils système et des bibliothèques pour exécuter
une application.

157
3 - Comment passer des variables dans un
Dockerfile ?

158
3 - Comment passer des variables dans un
Dockerfile ?

159
3 - Comment passer des variables dans un
Dockerfile ?

160
3 - TP1 : Dockerfile

❏ Mise en place d’un Dockerfile


❏ A partir de l’image node
❏ cloner le dépôt https://github.com/docker-in-practice/todo.git
❏ Répertoire de travail todo
❏ Lancer la commande npm install
❏ Ouvrir le port 8000
❏ Lancer la commande npm start

❏ Lancer le container et vérifier qu’il tourne

161
3 - TP1 : Dockerfile
FROM node
RUN git clone ...
WORKDIR todo
RUN npm install > /dev/null
EXPOSE 8000
CMD ["npm", "start"]

docker build -t todoapp .

docker run -i -t -p 8000:8000 --name example1 todoapp

162
3 - TP2 : Dockerfile
❏ Déploiement d’une appli React
❏ Les fichiers React sont donnés
❏ Démarrer de l’image node 9.11.1 et lui donner un alias
❏ Répertoire de travail : /usr/src/app
❏ Envoyer le package.json
❏ Faire les install de npm et de react-scripts et le build avec npm
❏ Pour l’environnement de prod, partir de nginx:1.13.12-alpine
❏ Envoyer le build dans les dossiers html de nginx
❏ Démarrer le serveur

❏ Lancer le container et vérifier qu’il tourne

163
3 - TP2 : Dockerfile
### STAGE 1: Build ###
FROM node:9.11.1 as builder
RUN mkdir /usr/src/app
WORKDIR /usr/src/app
ENV PATH /usr/src/app/node_modules/.bin:$PATH
COPY package.json /usr/src/app/package.json
RUN npm install --silent
RUN npm install react-scripts -g --silent
COPY . /usr/src/app
RUN npm run build

### STAGE 2: Production Environment ###


FROM nginx:1.13.12-alpine
COPY --from=builder /usr/src/app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

164
3 - Comment exporter l’image ?
Docker Export (docker export) fait référence à la commande qui est utilisée pour exporter le fichier d'un conteneur
Docker en tant qu'archive, qui peut ensuite être importée en tant qu'image Docker.

Il inclut tous les fichiers et dossiers créés dans le conteneur, bien qu'il n'exporte pas les données qui sont placées
sur le conteneur. La commande Docker est utilisée pour créer un seul calque ou une image Docker afin d'améliorer
les performances ou de les partager sans utiliser le registre Docker.

docker export [OPTIONS] container

165
3 - Comment exporter l’image ?

Après avoir exécuté la commande docker export –help , le système de fichiers du conteneur est enregistré en tant
qu'archive et une image Docker plate est créée. Cette image Docker plate diminue la taille de l'image Docker.

Cependant, il perd les métadonnées ainsi que l'historique, ce qui signifie que vous ne pouvez pas revenir au calque
précédent si une image Docker est importée avec un fichier tar exporté.

L'objectif principal de Docker est de développer un environnement cohérent entre tous les appareils compatibles
Docker ainsi que de créer des modèles ou des images pouvant s'exécuter sur n'importe quel serveur activé par
Docker. Cela simplifie l'exportation d'un conteneur, puis sa réimportation sur un autre serveur compatible Docker.

166
3 - Comment exporter l’image ?

Voici les étapes pour exporter une image Docker :

● Étape 1 : Sélectionnez l'ID du conteneur Docker que vous souhaitez déplacer.


● Étape 2 : Apportez des modifications, puis enregistrez le conteneur dans une nouvelle image sous le nom «
mynewimage ».
● Étape 3 : Enregistrez maintenant cette « mynewimage » dans un fichier tar. Vous pouvez utiliser un partage
NFS pour déplacer le fichier tar

$ docker save mynewimage > /tmp/mynewimage.tar

167
3 - Comment exporter l’image ?

● Étape 4 : Ensuite, copiez le « mynewimage.tar » dans la nouvelle instance Docker en utilisant n'importe quelle
méthode adaptée à votre environnement, comme FTP, SCP, etc.
● Étape 5 : Sur la nouvelle instance Docker, vous devez exécuter la commande Docker load en indiquant
l'emplacement exact du fichier image tar.

$ docker load < /tmp/mynewimage.tar

● Étape 6 : Enfin, exécutez la commande Docker image et vérifiez si l'image est disponible ou non.

168
3 - Comment exporter l’image ?

Avantages de Docker Export

1. Meilleur partage d'images - Tout en partageant l'image Docker, nous devons la déplacer vers un registre.
Cependant, avec l'aide de Docker export , nous pouvons exporter l'image Docker en tant qu'archive, et ainsi,
elle peut également être partagée avec d'autres.
2. Vitesse plus élevée - La vitesse de l' exportation Docker est plus rapide que la re-création de l'image Docker
sur un autre système.
3. Performant - Lorsque l'archive exportée est importée à l'aide de la commande d' importation Docker , une
image Docker à une seule couche est créée, améliorant ainsi les performances du conteneur.

169
3- docker pull ubuntu:18.04
docker run -itd --name ubuntu ubuntu:18.04 /bin/bash
Exportation docker exec -it ubuntu bash
mkdir aaa
d’une image ls -al
exit
export d’un container et save
une image. docker save ubuntu > ubuntu_save.tar
Il est important de sauver les docker export ubuntu > ubuntu_export.tar
changements dans le docker stop ubuntu
container docker rm ubuntu
docker rmi ubuntu:18.04
docker load < ubuntu_save.tar
docker run -itd --name ubuntu ubuntu:18.04 /bin/bash
docker exec -it ubuntu bash
ls -al
exit (puis effacer le container et l’image)
cat ubuntu_export.tar | sudo docker import - ubuntu:18.04
docker run -itd --name ubuntu ubuntu:18.04 /bin/bash
docker exec -it ubuntu bash
170
4 - Les registres d’images

171
4 - Les registres d’images
Docker Hub est le registre le plus populaire pour héberger des images.

C’est aussi le registre par défaut de Docker Engine

Une image Docker a besoin d’un nom

Les noms contiennent en général une ou deux parties : image-gallery ou


diamol/golang

172
4 - Les registres d’images

173
4 - Les registres d’images
Envoi sur Docker Hub

Conseiller de toujours utiliser un tag pour identifier les différentes versions

Sinon d’office tag latest qui peut écraser les tags précédents

Création d’un compte Docker Hub → https://hub.docker.com/

Deux choses à faire pour envoyer une image :

1. Log in
2. Donner une référence à une image qui inclut le nom du compte dans
lequel vous avez la permission d’envoyer

174
4 - Les registres d’images

175
4 - Les registres d’images

176
4 - Les registres d’images

export dockerId="<your-docker-id-goes-here>"

docker login --username $dockerId

C’est le Docker Engine qui envoie et récupère les images

Créons une référence pour l’image que nous avons générée :

docker image tag <nom_image> $dockerId/<nom_image>:v1

177
4 - Les registres d’images

Vérifions la référence de notre image :

docker image ls --filter reference=<nom_image> --filter


reference='*/<nom_image>'

Envoi vers le Docker Hub :


docker image push $dockerId/<nom_image>:v1

Possibilité de se créer son propre repo Docker avec le code source :


https://github.com/docker-archive/docker-registry

178
4 - Les registres d’images
Un registre Docker privé vous permet de partager vos images de base personnalisées au sein de votre
organisation, en gardant une source de vérité cohérente, privée et centralisée pour les blocs de construction
de votre architecture. Un registre Docker privé vous offre de meilleures performances pour les grands
clusters et les déploiements à haute fréquence, ainsi que des fonctionnalités supplémentaires telles que
l'authentification d'accès.

Un registre Docker n'est qu'un conteneur en cours d'exécution spécifique, un registre .

179
4 - Les registres d’images
docker run -d -p 5000:5000 --restart=always --name registry registry:2

Cette commande :
■ télécharge l'image de registre qui est étiquetée 2. Cette balise fait référence à la dernière
version du registre au moment de la rédaction de cet article.
■ expose le port 5000 à l'hôte, sous le même port
■ donne le nom registry au conteneur au lieu de lui attribuer un nom aléatoire

Pour vous assurer que le registre est en cours d'exécution, un simple docker ps devrait afficher sa présence.

180
4 - Les registres d’images
Il existe une nette différence entre une image disponible pour Docker et une image stockée dans un registre
Docker.
■ Dans le premier cas, il peut être listé et exécuté par le démon Docker auquel il appartient.
■ Dans le second cas, il ne le peut pas.
Pour qu'une image stockée dans un registre soit exécutée, elle doit d'abord être extraite vers une instance
Docker.
Il y a cependant une contrainte, le nom de l'image doit être préfixé par l'URL du registre (qu'elle soit basée sur
le domaine ou IP), le port inclus, par exemple 159.100.243.157:5000/hello-world .
Nous utilisons pour cela la commande docker tag :

docker tag hello-world 159.100.243.157:5000/hello-world # Replace with your IP/domain

181
4 - Les registres d’images
La nouvelle étiquette devrait maintenant apparaître : docker images

Bien que répertoriée avec deux étiquettes différentes après avoir lancé la commande du tag, la même image hello-world est
référencée, de sorte que l'espace disque n'est utilisé qu'une seule fois. Vous pouvez vous en assurer en regardant l'ID de l'image avec
docker images
Les étiquettes sont en fait assez similaires aux liens créés par la commande ln. Si vous supprimez l'une des étiquettes, l'image sera
toujours disponible avec l'autre. Afin de supprimer complètement l'image, elle doit être référencée sans étiquette.
Nous pouvons maintenant pousser l'image vers le registre, avec la commande docker push :

docker push 159.100.243.157:5000/hello-world

182
4 - Les registres d’images

Cependant nous pourrons certainement avoir l’erreur suivante :

The push refers to repository [159.100.243.157:5000/hello-world]

Get https://159.100.243.157:5000/v2/: http: server gave HTTP response to HTTPS client

Docker attend un canal sécurisé par défaut, et c'est naturellement une très bonne chose. Mais TLS
ajoute une autre couche de complexité et des problèmes possibles

183
4 - Les registres d’images

La configuration de Docker pour accepter les connexions à des registres non sécurisés dépend de votre
système d'exploitation , mais c'est assez simple. Dans tous les cas, vous devrez mettre à jour un fichier
daemon.json.
Sous Linux, le fichier .json se trouve /etc/docker/daemon.json et en supposant qu'aucun autre paramètre ne
soit présent dans le fichier, il devrait ressembler à ceci :

184
4 - Les registres d’images
Vous pouvez créer le fichier s'il n'existe pas, et vous devrez redémarrer Docker par la suite pour que les
modifications prennent effet. Sur macOS, vous le faites à l'aide de l'interface utilisateur et les modifications
redémarreront automatiquement le daemon :

1. Cliquez sur l'icône Docker


2. Sélectionnez Préférences… dans le menu
3. Sélectionnez l'onglet Démon
4. Cochez la case intitulée Fonctionnalités expérimentales
5. Dans la première zone de liste, entrez l'adresse (URL ou IP) du registre non sécurisé par
exemple 159.100.243.157:5000

185
4 - Les registres d’images

Attendez un peu que le daemon Docker redémarre, puis appuyez à nouveau sur le registre avec la même
ligne de commande que ci-dessus. Cette fois, ça devrait fonctionner :

The push refers to repository [159.100.243.157:5000/hello-world]


428c97da766c: Pushed

latest: digest: sha256:1a6fd470b9ce10849be79e99529a88371dff60c60aab424c077007f6979b4812

size: 524

186
4 - Les registres d’images

L'image devrait maintenant être stockée en toute sécurité dans le registre Docker que nous avons
configuré. Pour s'en assurer, on peut demander à ce registre distant quelles images il contient.
Heureusement, le registre propose également une API Web pour interroger les images stockées.

Depuis n’importe quelle machine, tapez :

curl -X GET http://159.100.243.157:5000/v2/_catalog

{"repositories":["hello-world"]}

187
4 - Les registres d’images
Docker Trusted Registry https://hub.docker.com/r/docker/dtr-registry

https://www.docker.com/blog/dtr/

188
5 - La persistance des données ou les volumes

Les images sont construites de manière à garder les conteneurs basés sur elles petits, portable et
jetables. Par exemple, les images ne contiendront généralement que le packages nécessaires pour
fournir le service prévu.

Idéalement, il est préférable de pouvoir jeter un conteneur sans craindre de perdre des données
importantes.

Si possible, vous ne voulez pas que les données importantes n'existent qu'à l'intérieur d'un conteneur.
Cela signifie que si vous souhaitez conserver – ou sauvegarder – les données générées ou utilisées
par un conteneur, vous aurez envie d'utiliser un volume. Un volume est aussi le choix idéal, si vous
voulez partager les mêmes données entre plusieurs conteneurs.

189
5 - La persistance des données ou les volumes

190
5 - La persistance des données

191
5 - La persistance des données

Définition du volume en CLI


ou dans le Dockerfile comme
vue précédemment

192
5 - La persistance des données

193
5 - La persistance des données

194
5 - La persistance des données

195
5 - La persistance des données

Nous pouvons utiliser l'option "-v" pour une commande "docker run" pour utiliser un volume
avec un conteneur.

L'abrégé "-v" est exactement la même que l'option "--volume". Cependant, la plus récente
et la méthode préférée pour monter des volumes dans un conteneur est l'option "--mount".
Docker vous recommande d'utiliser "--mount" au lieu de "-v" ou "--volume", car
leurs recherches ont montré que "--mount" est plus facile à utiliser.

Dans tous les cas, l'un ou l'autre fonctionne, mais nous allons nous concentrer sur "--mount",
car c'est la manière recommandée.

196
5 - La persistance des données
docker volume --help
CRÉATION D’UN VOLUME
docker volume create testdata

docker volume ls

docker volume rm testdata

docker volume ls

docker volume create mydata1

docker volume ls
197
5 - La persistance des données
Comme vous pouvez le voir, la
docker volume inspect mydata1 section "Mounts" montre que
"/root/volume" est la destination du
volume à l'intérieur de notre
docker run -d --name withvolume --mount conteneur, et il est configuré pour
source=mydata1,destination=/root/volume nginx lire et écrire, comme indiqué par le
"RW": true
Remarquez le long chemin
docker ps commençant par "/var/lib". C'est le
chemin de volume interne que
docker inspect withvolume | grep Mounts -A10 Docker utilise sur le disque de notre
machine hôte. C'est la source.

198
5 - La persistance des données
echo 'Hello from the mydata1 volume!' >
/var/lib/docker/volumes/mydata1/_data/index.html

cat /var/lib/docker/volumes/mydata1/_data/index.html

docker exec -it withvolume /bin/bash

pwd

cd /root/volume

ls

cat index.html

exit
199
5 - La persistance des données

Docker nous permet de monter ce volume sur d’autres containers

docker run -d --name withvolume2 --mount src=mydata1,dst=/root/volume nginx

docker exec -it withvolume2 /bin/bash

cat /root/volume/index.html

exit

200
5 - La persistance des données
❏ LIRE DES VOLUMES ET Y ÉCRIRE

Nous ne voulons pas que le container puisse changer le contenu du volume → accès en read-only au
volume

docker run -d --name readcontainer --mount


src=newestvolume,dst=/usr/share/nginx/html,readonly nginx

docker ps

docker volume ls

docker inspect readcontainer | grep Mounts -A10

201
5 - La persistance des données
❏ LIRE DES VOLUMES ET Y ÉCRIRE

Notez que la section du bas signale « RW » est à false. RW, comme on peut s'y attendre,
signifie lecture-écriture. Donc, si RW est faux, cela signifie qu'il n'est pas "lu et écrire". Plus
simplement, cela signifie que le volume est en lecture seule à partir du récipient. Vous pouvez utiliser
ce volume en lecture et en écriture avec d'autres conteneurs, ou directement à partir de l'hôte Docker
lui-même, mais pour ce conteneur, il est en lecture seule pour ce volume.
L'utilisation de cette option en lecture seule est une bonne pratique de sécurité lorsque la lecture-
écriture n'est pas obligatoire. Si un conteneur est compromis dans une faille de sécurité, le
les fichiers de votre volume peuvent rester intacts par la suite.
Si vous le souhaitez, vous pouvez également autoriser certains conteneurs à accéder pleinement à un
volume et forcer les autres conteneurs à n'avoir qu'un accès en lecture seule au même volume.
La possibilité d'écrire sur le volume est définie au niveau du conteneur, pas au niveau du volume.
Prouvons que le volume est bien monté en lecture seule à l'intérieur du conteneur.

202
5 - La persistance des données
❏ LIRE DES VOLUMES ET Y ÉCRIRE

docker exec -it readcontainer bash

touch /usr/share/nginx/html/test

exit

docker inspect ephemeral | grep Mounts -A10

203
5 - La persistance des données

Pour qu’un volume soit en read-only, il est également possible


d’utiliser le tag :ro :
FROM ubuntu
ADD file1 /ubuntu1/file
VOLUME /ubuntu1
CMD /bin/sh

docker build -t test/volume-one-dockerfile .

$ docker run -it -v /ubuntu2:/ubuntu2:ro


test/volume-one-dockerfile

# touch /ubuntu2/file3
touch: cannot touch '/ubuntu2/file3': Read-only file system

204
5 - La persistance des données
❏ LIRE DES VOLUMES ET Y ÉCRIRE

Comme vous pouvez le voir sous "type", ce conteneur est connecté à un volume "tmpfs" par opposition au
"type" rapportant "volume" comme auparavant.
Vous pouvez également ajouter une taille statique au volume après l'entrée "type=tmpfs" pour
gardez un œil sur les limites d'espace disque.
Voici un exemple de la façon de procéder :

docker run -dit --name ephemeral2 --mount


type=tmpfs,tmpfs-size=256M,destination=/root/volume nginx

docker exec -it ephemeral2 df -h /root/volume

205
5 - La persistance des données

❏ LIRE DES VOLUMES ET Y ÉCRIRE

Attention toutefois : Une limitation est que vous ne pouvez pas partager les volumes "tmpfs" entre les
conteneurs.
De plus,puisque ces types de volumes disparaissent après l'arrêt du conteneur, ils peuvent rendre plus
difficile le diagnostic des problèmes, s'ils surviennent.

206
5 - La persistance des données
❏ LIRE DES VOLUMES ET Y ÉCRIRE avec l’option -v

docker run -p 8080:80 --name nginx-with-vol -v


${PWD}/webpages:/usr/share/nginx/html:ro -d nginx

docker ps

docker inspect nginx-with-vol | grep Mount -A10

207
5 - La persistance des données
docker stop nginx-with-vol ephemeral2 ephemeral readcontainer withvolume2
withvolume

docker rm nginx-with-vol ephemeral2 ephemeral readcontainer withvolume2


withvolume

docker ps -a

docker volume ls

docker volume prune --help

docker volume prune


208
5 - La persistance des données

Choisir l’option -v ou --mount


En général, --mount est plus explicite et verbeux. La plus grande différence est que la syntaxe -v combine toutes
les options dans un seul champ, tandis que la syntaxe --mount les sépare. Voici une comparaison de la syntaxe
pour chaque drapeau.

Astuce : Les nouveaux utilisateurs doivent utiliser la syntaxe --mount. Les utilisateurs expérimentés

peuvent être plus familiers avec la syntaxe -v ou --volume, mais sont encouragés à utiliser --mount, car la

recherche a montré qu'il est plus facile à utiliser. (Documentation de Docker)

209
5 - La persistance des données
Bind Mount : montage d’un répertoire de l’hôte dans un container.
Les bind mounts existent depuis les premiers jours de Docker. Les bind mounts ont des fonctionnalités limitées par rapport aux
volumes . Lorsque vous utilisez un bind mount, un fichier ou un répertoire sur la machine hôte est monté dans un conteneur. Le
fichier ou le répertoire est référencé par son chemin absolu sur la machine hôte. En revanche, lorsque vous utilisez un volume, un
nouveau répertoire est créé dans le répertoire de stockage de Docker sur la machine hôte, et Docker gère le contenu de ce
répertoire.

Le fichier ou le répertoire n'a pas besoin d'exister déjà sur l'hôte Docker. Il est créé à la demande s'il n'existe pas encore. Les bind
mounts sont très performants, mais ils reposent sur le système de fichiers de la machine hôte ayant une structure de répertoires
spécifique disponible. Si vous développez de nouvelles applications Docker, envisagez plutôt d'utiliser des volumes nommés .
Vous ne pouvez pas utiliser les commandes Docker CLI pour gérer directement les bind mounts.

210
5 - La persistance des données
docker run -d \
-it \
--name devtest \
--mount type=bind,source="$(pwd)"/target,target=/app \
nginx:latest

docker run -d \
-it \
--name devtest \
-v "$(pwd)"/target:/app \
nginx:latest

Utilisez docker inspect devtest pour vérifier que le montage de liaison a été créé correctement. Recherchez la rubrique Mounts

211
5 - La persistance des données

Si vous souhaitez que votre stockage ou votre couche persistante soit entièrement géré par
Docker et accessible uniquement via les conteneurs Docker et la CLI Docker, vous devez choisir
d'utiliser des volumes.

Cependant, si vous avez besoin d'un contrôle total du stockage et prévoyez d'autoriser d'autres
processus en plus de Docker à accéder ou à modifier la couche de stockage, alors les montages
de liaison sont les bons outils pour le travail.

212
5 - La persistance des données
Selon la documentation Docker, l'utilisation de volumes est le moyen le plus simple de commencer
à conserver les données dans votre conteneur Docker. Dans l'ensemble, les montures de liaison
sont plus limitées en comparaison.

Cette idée n'est pas surprenante d'après ce que nous avons vu jusqu'à présent. Une bonne règle de
base est que si vous avez des doutes sur la voie à suivre pour conserver les données dans vos
conteneurs Docker, utilisez des volumes.

L'un des principaux différenciateurs d'un montage lié est qu'un montage lié peut être consulté et
modifié par des processus extérieurs à Docker. Comme mentionné précédemment, cela peut être un
avantage lorsque vous souhaitez intégrer Docker à d'autres processus, mais cela peut également
causer des maux de tête si vous êtes préoccupé par la sécurité.

213
5 - La persistance des données
D'une part, les volumes sont partagés de manière plus sûre entre les conteneurs ; ils ne peuvent être
spécifiés que dans un seul répertoire ( ) et sont entièrement gérés par Docker lui-même. Vous
pouvez également stocker des volumes en dehors de votre machine hôte sur des hôtes distants ou
des fournisseurs de cloud.$HOME/docker/volumes

Vous pouvez gérer les volumes à l'aide de Docker CLI et de l'API Docker, et vous pouvez pré-remplir
le contenu d'un nouveau volume à partir d'un conteneur. De plus, les volumes fonctionnent à la fois
sur Linux et Windows, ce qui le rend parfait pour les équipes utilisant les deux systèmes
d'exploitation.

Après avoir étudié à la fois les volumes et les montages de liaison, nous avons constaté que les
volumes sont la meilleure option pour la persistance des données le plus souvent.

214
5 - La persistance des données
bind mount de la socket unix du Docker Daemon

docker.sock est le socket UNIX que le démon Docker écoute. C'est le point d'entrée principal de l'API Docker. Il peut également
s'agir d'un socket TCP, mais par défaut pour des raisons de sécurité, Docker utilise par défaut le socket UNIX.
Le client Docker cli utilise ce socket pour exécuter les commandes docker par défaut. Vous pouvez également remplacer ces
paramètres.
Il peut y avoir différentes raisons pour lesquelles vous devrez peut-être monter le socket Docker à l'intérieur d'un conteneur.
Comme lancer de nouveaux conteneurs à partir d'un autre conteneur. Ou à des fins de découverte de service automatique et de
journalisation. Cela augmente la surface d'attaque, vous devez donc faire attention si vous montez un socket docker dans un
conteneur, des codes de confiance s'exécutent à l'intérieur de ce conteneur, sinon vous pouvez simplement compromettre votre
hôte qui exécute le démon docker, car Docker lance par défaut tous les conteneurs en tant que root.
Docker socket a un groupe docker dans la plupart des installations afin que les utilisateurs de ce groupe puissent exécuter des
commandes docker contre docker socket sans autorisation root, mais les conteneurs docker réels obtiennent toujours
l'autorisation root puisque le démon docker s'exécute efficacement en tant que root (il a besoin de l'autorisation root pour
accéder à l'espace de noms et aux groupes de contrôle) .

215
5 - La persistance des données
Le démon Docker peut écouter les requêtes de l' API Docker Engine via trois types de socket différents : unix, tcp, et fd.

Par défaut, un socket unix de domaine (ou socket IPC) est créé sur /var/run/docker.sock, nécessitant soit une
autorisation root, soit une appartenance docker à un groupe.

Si vous devez accéder au daemon Docker à distance, vous devez activer le Socket tcp. Attention, la configuration par
défaut fournit un accès direct non crypté et non authentifié au démon Docker - et doit être sécurisée soit à l'aide du socket
crypté HTTPS intégré , soit en plaçant un proxy Web sécurisé devant celui-ci. Vous pouvez écouter sur le port 2375 sur
toutes les interfaces réseau avec -H tcp://0.0.0.0:2375, ou sur une interface réseau particulière en utilisant son adresse IP :
-H tcp://192.168.59.103:2375. Il est classique d'utiliser un port 2375 pour une communication non cryptée et un port 2376
pour une communication cryptée avec le daemon.

216
5 - La persistance des données
Le client Docker utilisera la variable d'environnement DOCKER_HOST pour définir l'indicateur -H pour le client. Utilisez l'une des
commandes suivantes :

$ docker -H tcp://0.0.0.0:2375 ps

$ export DOCKER_HOST="tcp://0.0.0.0:2375"
$ docker ps

217
5 - La persistance des données
Liez Docker à un autre hôte/port ou à un socket Unix
Avertissement

Changer la liaison docker par défaut du démon à un port TCP ou à un groupe d'utilisateurs Docker Unix augmentera vos risques de

sécurité en permettant aux utilisateurs non root d'obtenir un accès root sur l'hôte. Assurez-vous de contrôler l'accès à docker. Si vous vous

connectez à un port TCP, toute personne ayant accès à ce port dispose d'un accès Docker complet ; il n'est donc pas conseillé sur un

réseau ouvert.

Avec -H il est possible de faire en sorte que le démon Docker écoute sur une IP et un port spécifiques. Par défaut, il écoutera
unix:///var/run/docker.sock pour autoriser uniquement les connexions locales par l' utilisateur root . Vous pouvez le définir sur 0.0.0.0:2375

ou sur une adresse IP d'hôte spécifique pour donner accès à tout le monde, mais ce n'est pas recommandé car il est alors trivial pour quelqu'un
d'obtenir un accès root à l'hôte sur lequel le démon s'exécute.

218
5 - La persistance des données
Liez Docker à un autre hôte/port ou à un socket Unix
De même, le client Docker peut utiliser -H pour se connecter à un port personnalisé. Le client Docker se connectera par défaut à
unix:///var/run/docker.sock pour Linux et tcp://127.0.0.1:2376 pour Windows.

-H accepte l'affectation d'hôte et de port au format suivant :

tcp://[host]:[port][path] or unix://path

219
6 - Mettre en oeuvre une application
multi-conteneurs # This is the app definition for running in dev.
# It uses a Sqlite database inside the web app
container.
version: "3.7"

L’idée est de pouvoir lancer une services:


structure contenant plusieurs todo-web:
image: diamol/ch06-todo-list
containers. ports:
- "8020:80"
Appli côté client → API Docker environment:
- Database:Provider=Sqlite
Le fichier Docker Compose décrit l’état networks:
désiré de l’application quand tout est - app-net
lancé
networks:
Format YAML (indentation!) app-net:
external:
name: nat
220
6 - Mettre en oeuvre une application
multi-conteneurs
L’idée est de pouvoir lancer une structure contenant plusieurs containers

Le fichier Docker Compose décrit l’état désiré de l’application quand tout


est lancé

Format YAML (indentation!)

Installation : $ sudo apt-get install docker-compose

221
6 - Mettre en oeuvre une application
multi-conteneurs
● version : version de Docker Compose
● services : liste tous les composants pour construire l’app. Un service
peut contenir plusieurs containers de la même image (scaling)
● networks : liste tous les réseaux Docker sur lesquels le service peut se
connecter
● service todo-web : lance un container depuis une image, publie le port
8020 de l’hôte sur le port 80 du container, et connectera le container à
un réseau nommé app-net
Cela revient à faire la commande suivante :
docker run -p 8020:80 --name todo-web --network nat diamol/ch06-todo-list

222
6 - Mettre en oeuvre une application
multi-conteneurs

● external : option qui signifie que le Compose s’attend que le réseau nat
existe déjà et qu’il ne doit pas le créer
● Dans le dossier contenant le docker-compose.yaml :

docker network create nat


http://localhost:8020
docker-compose up

223
version: '3.7'

6 - Mettre en oeuvre une


services:

accesslog:

application
image: diamol/ch04-access-log
networks:
- app-net

multi-conteneurs iotd:
image: diamol/ch04-image-of-the-day
ports:
- "80"
● service iotd : attribue un port networks:
- app-net
aléatoire de l’hôte en relation avec le
image-gallery:
port 80 du container image: diamol/ch04-image-gallery
ports:

● depends_on : dépendant de ces - "8010:80"


depends_on:
- accesslog
deux services, démarrés avant - iotd
networks:
- app-net

networks:
app-net:
external:
name: nat

224
6 - Mettre en oeuvre une
application
multi-conteneurs

docker-compose up --detach

Mode detach pour retrouver la main sur


le terminal

localhost:8010 Réseau

Pour visualiser la structure de votre Compose : https://github.com/pmsipilot/docker-compose-viz


225
6 - Mettre en oeuvre une application
multi-conteneurs

Possibilité d’augmenter le nombre de container : scaling sur le service iotd

docker-compose up -d --scale iotd=3

# aller sur localhost://localhost:8010 et rafraîchir

docker-compose logs --tail=1 iotd

Maintenant Docker Compose manage 5 containers


226
6 - Mettre en oeuvre une application
multi-conteneurs
Arrêter et redémarrer l’application avec CLI :

docker-compose stop

docker-compose start

docker container ls

Docker Compose va lister les containers à l’arrêt mais seulement les services au démarrage

227
6 - Mettre en oeuvre une application
multi-conteneurs
Arrêter l’application et la relancer encore, puis vérifier le nombre de containers actifs :

docker-compose down

docker-compose up -d

docker container ls

down efface toute l’application. up relance l’appli depuis le yaml

228
6 - Mettre en oeuvre une application
multi-conteneurs
Comment les composants de l’appli communiquent entre eux ?

Chaque container a une adresse IP virtuelle et les containers reliés à un même réseau peuvent
accéder aux IP des autres.

Mais très souvent des containers sont supprimés et les nouveaux auront d’autres adresses IP.

⇒ Docker possède un service de DNS discovery pour lier les IP

Les applications exécutées dans des conteneurs effectuent des recherches de domaine lorsqu'elles tentent
d'accéder à d'autres composants. Le service DNS de Docker effectue cette recherche : si le nom de domaine
est en fait un nom de conteneur, Docker renvoie l'adresse IP du conteneur et le consommateur peut travailler
directement sur le réseau Docker. Si le nom de domaine n'est pas un conteneur, Docker transmet la demande
au serveur sur lequel Docker s'exécute. Il effectuera donc une recherche DNS standard pour trouver une
adresse IP sur le réseau de votre organisation ou sur l'Internet public.

229
6 - Mettre en oeuvre une application
multi-conteneurs
docker-compose up -d --scale iotd=3

docker container exec -it docker_scripts_image-gallery_1 sh

nslookup accesslog

exit

nslookup est un petit utilitaire, il donne le DNS et l’IP

Le service DNS permet de garder les connexions même si les DNS et les IP changent

230
6 - Mettre en oeuvre une application
multi-conteneurs
docker container rm -f docker_scripts_accesslog_1

docker-compose up -d --scale iotd=3

docker container exec -it docker_scripts_image-gallery_1 sh

nslookup accesslog

nslookup iotd

exit

231
6 - Mettre en oeuvre une application
multi-conteneurs

Les serveurs DNS peuvent renvoyer plusieurs adresses IP pour un nom de domaine. Docker
Compose utilise ce mécanisme pour un équilibrage de charge simple, renvoyant toutes les adresses
IP de conteneur pour un service. C'est à l'application de faire la recherche DNS pour savoir comment
elle traite les réponses multiples

Pour essayer de fournir un équilibrage de charge sur tous les conteneurs, le Docker DNS renvoie la
liste dans un ordre différent à chaque fois. Vous verrez que si vous répétez l'appel nslookup pour le
service iotd, c'est un moyen basique d'essayer de répartir le trafic autour de tous les conteneurs.
Docker Compose enregistre toutes les options de démarrage de vos conteneurs et prend en charge la
communication entre les conteneurs lors de l'exécution.

232
version: "3.7"

services:

6 - Mettre en oeuvre une todo-db:


image: diamol/postgres:11.5

application
ports:
- "5433:5432"
networks:

multi-conteneurs : TP - app-net

todo-web:
image: diamol/ch06-todo-list
Mettre en place un postgres avec le ports:
container todolist avec un fichier config à - "8030:80"
environment:
la racine qui contiendra les informations - Database:Provider=Postgres
de connection à la database depends_on:
- todo-db
networks:
- app-net
{ secrets:
"ConnectionStrings": { - source: postgres-connection
"ToDoDb": "Server=todo-db;Database=todo;User target: /app/config/secrets.json

Id=postgres;Password=postgres;"
networks:
} app-net:
}
secrets:
postgres-connection:
233
file: ./config/secrets.json
6 - Mettre en oeuvre une application
multi-conteneurs
docker-compose up -d
localhost:8030
docker-compose ps

#database
psql -h localhost -p 5433 -U postgres -d todo
\list
\dt
select * from "ToDos";

234
6 - Mettre en oeuvre une application
multi-conteneurs

235
6 - Mettre en oeuvre une application
multi-conteneurs

Compose vous permet de définir votre application et d'appliquer les définitions à une seule machine
exécutant Docker.
Il compare les ressources Docker en direct sur cette machine avec les ressources décrites dans le
fichier Compose, et il enverra des demandes à l'API Docker pour remplacer les ressources qui ont été
mises à jour et créer de nouvelles ressources là où elles sont nécessaires.
Vous obtenez l'état souhaité de votre application lorsque vous exécutez docker-compose, mais c'est là
que Docker Compose se termine. Ce n'est pas une plate-forme de conteneur complète comme Docker
Swarm ou Kubernetes - elle ne s'exécute pas en permanence pour s'assurer que votre application
conserve l'état souhaité. Si les conteneurs échouent ou si vous les supprimez manuellement, Docker
Compose ne redémarrera ou ne les remplacera pas tant que vous n'aurez pas explicitement réexécuté
docker-compose.

236
6 - Mettre en oeuvre une application
multi-conteneurs
Cela ne veut pas dire que Docker Compose n'est pas adapté à la production.
Si vous débutez avec Docker et que vous migrez des charges de travail de machines virtuelles
individuelles vers des conteneurs, cela peut être un bon point de départ.
Vous n'obtiendrez pas de haute disponibilité, d'équilibrage de charge ou de basculement sur cette
machine Docker, mais vous ne l'avez pas non plus sur vos machines virtuelles d'application
individuelles.
Vous obtiendrez un ensemble cohérent d'artefacts pour toutes vos applications et vous obtiendrez des
outils cohérents pour déployer et gérer vos applications. Cela pourrait suffire pour vous aider à
démarrer avant de vous pencher sur le lancement d’un cluster de conteneurs.

237
6 - Mettre en oeuvre une application
multi-conteneurs
Le binaire Docker Compose

https://hub.docker.com/r/gists/docker-compose-bin#!

https://docs.docker.com/compose/install/

238
7 - Intégration avec GitLab CI et
registry
Comment créer une image Docker et la transmettre au registre de conteneurs GitLab à partir d'un
pipeline GitLab CI :

Bien que Dockerhub soit un registre public essentiellement utilisé par tout le monde, vous n'avez pas
toujours besoin de l'utiliser. Vous pouvez créer vos propres images Docker et les publier dans le registre
de conteneurs GitLab, qui peut servir de registre privé.

239
7 - Intégration avec GitLab CI et
registry
Vous vous demandez peut-être s'il existe un moyen de stocker des images Docker sur GitLab et de les utiliser

dans des pipelines. Il existe de nombreuses raisons pour lesquelles vous souhaiterez peut-être utiliser le registre

de conteneurs GitLab. Il existe deux cas d'utilisation typiques :

● pour stocker vos applications dockerisées

● pour utiliser votre propre image Docker dans le pipeline GitLab CI

240
7 - Intégration avec
GitLab CI et
registry

Gitlab est un ensemble de


microservices qui se
coordonnent

241
7 - Intégration avec GitLab CI et
registry
● Comment créer et envoyer une image Docker vers le registre de conteneurs GitLab ?

● Comment déterminer la taille des images Docker que vous utilisez ?

● Comment utiliser une image Docker du registre de conteneurs GitLab dans un pipeline GitLab

CI ?

242
7 - Intégration avec GitLab CI et
registry
Il est tout à fait possible également d’installer GitLab en local avec plusieurs outils différents de Docker :

https://docs.gitlab.com/ee/install/docker.html

Après avoir lancé le compose, il faut récupérer l’ip du container. docker inspect <nom_container>

docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container_name_or_id

Dans le compose, il s’attend à ce que nous le contactions avec gitlab.com

Donc nous devons le réorienter dans le fichier /etc/hosts

243
7 - Intégration avec GitLab CI et
registry
Puis nous vérifions les logs : docker logs <nom_container>

244
7 - Intégration avec GitLab CI et
registry
Puis nous vérifions les logs : docker logs <nom_container>

Aller sur l’adresse, créer un utilisateur et lancer un nouveau projet

Arrêter le container proprement avec docker-compose down

Vous pouvez aller checker les datas sur /srv/gitlab et la config dans gitlab.rb

245
7 - Intégration avec GitLab CI et
registry
Simplement pour activer le registry il faut décommenter ces lignes

Puis monter le volume indiqué en dernière ligne également

246
7 - Intégration avec GitLab CI et
registry
Assez souvent, lors de la création d'un pipeline GitLab CI, vous commencez avec une image
Docker de base de Dockerhub et vous ajoutez les dépendances manquantes. Voici une version
très simplifiée où pytest s'installe en dépendance :
some test job:
image: python
script:
- python --version
- pip --version
- pip install pytest
- pytest --version
- echo "pytest est OK"

247
7 - Intégration avec GitLab CI et
registry
La première étape consiste à créer un Dockerfile. Pour l'exemple ci-dessus, le fichier
ressemblerait à ceci :

FROM python:3.10
RUN pip install pytest

248
7 - Intégration avec GitLab CI et registry
Que vous créiez une image Docker personnalisée ou que vous utilisiez une image du registre public

Dockerhub, connaître la taille de vos images est essentiel pour optimiser les performances de votre

pipeline.

Prenons par exemple une image Docker contenant Python. Depuis la page Python officielle sur Dockerhub

, cliquez sur Tags .

249
7 - Intégration avec GitLab CI et registry
Cela affichera toutes les différentes
versions disponibles. Comme vous
pouvez le remarquer, la dernière
version a plus de 300 Mo !

250
7 - Intégration avec GitLab CI et registry
Il s'agit d'une version complète de l'image Docker avec de nombreux packages Linux. Mais pour chaque
travail qui utilise cette image, vous devez télécharger 300 Mo avant de pouvoir faire quoi que ce soit.

Mais voici le problème : vous n'aurez peut-être pas besoin de toutes les dépendances de cette image
complète. Très souvent, les images Docker sont disponibles pour les petites distributions Linux, comme
Alpine Linux . Dans ce cas, la version Alpine Linux ne dispose que de 17 Mo.

251
7 - Intégration avec GitLab CI et registry
La différence vient du fait qu'Alpine Linux est vraiment léger et qu'il manque de nombreux packages,
dont cURL.

Il existe également une balise alternative à Alpine Linux : slim ; il s'agit d'un type d'image Docker qui a
été minimisé avec DockerSlim .

Je recommande donc fortement


d'essayer les petits paquets.
Utilisez le champ de recherche
pour localiser la version de l'image
que vous souhaitez utiliser.

252
7 - Intégration avec GitLab CI et registry
Affichage du registre de
conteneurs GitLab
Tout d'abord, assurez-vous que GitLab
Container Registry est activé en accédant à
votre projet et en sélectionnant Packages &
Registries > Container Registry .

253
7 - Intégration avec GitLab CI et registry

À ce stade, le registre sera vide car nous n'avons


pas encore poussé d'images.

Si vous utilisez GitLab.com avec un compte privé


qui ne fait pas partie d'une organisation, cela doit
être activé par défaut. Si ce n'est pas le cas, vous
devrez peut-être demander à votre administrateur
les autorisations nécessaires.

254
7 - Intégration avec GitLab CI et registry

Créez et transférez une image Docker vers le registre de


conteneurs GitLab
La création et la diffusion d'une image Docker nécessitent Docker. Nous devons donc utiliser l'image
Docker mais aussi démarrer le daemon Docker en utilisant Docker-in-Docker (done) en tant que service.

build image:
image: docker
services:
- docker:dind

255
7 - Intégration avec GitLab CI et registry

Il est considéré comme une mauvaise pratique d'utiliser la dernière version d'une image Docker car cela
changera toujours et pourrait casser votre pipeline. La version que vous utilisez change tout le temps si
vous :

● ne spécifiez pas de version (par exemple docker)


● utiliser la dernière balise (par exemple docker:latest)
● utilisez la balise stable (par exemple docker:stable)
● utiliser une balise de version majeure (par exemple docker:20)

256
7 - Intégration avec GitLab CI et registry

Considérer ce qui suit:

● Utilisez une version spécifique , comme docker:20.10.10& docker:20.10.10-dind(recommandé).


● Connectez-vous avec la version --version(cela peut vous aider à déterminer quelle était la version
qui a fonctionné).

Recherchez donc une version de Docker qui fonctionne pour vous et essayez de l'utiliser. Je vais utiliser la
version 20.10.10.
build image:
image: docker:20.10.10
services:
- docker:20.10.10-dind

257
7 - Intégration avec GitLab CI et registry
Alors maintenant que nous connaissons la taille des images Docker que nous utilisons,
allons de l'avant et adaptons le Dockerfile en spécifiant une image de base plus petite
qui utilise Alpine Linux :

FROM python:3.10-alpine
RUN pip install pytest

258
7 - Intégration avec GitLab CI et registry
Nous pourrions créer cette image à partir de notre ordinateur et la transmettre au registre de conteneurs
GitLab, mais nous allons utiliser l'automatisation. Définissons donc un nouveau travail dans notre pipeline.
Cela peut faire partie du même pipeline qui a besoin de l'image :

La première étape consiste à se connecter au registre de conteneurs GitLab à l'aide de docker login .
Étant donné que notre intention est d'utiliser cette commande à partir d'un pipeline GitLab CI, nous n'avons
pas besoin de connaître ou de générer des informations d'identification. Nous pouvons simplement
référencer les variables d'environnement CI_REGISTRY_USER, CI_REGISTRY_PASSWORD et
CI_REGISTRY.

echo $CI_REGISTRY_PASSWORD | docker login -u $CI_REGISTRY_USER $CI_REGISTRY --password-stdin

259
7 - Intégration avec GitLab CI et registry
docker login préfère obtenir le mot de passe à partir de l'entrée standard, c'est pourquoi j'utilise la
commande echo pour le rediriger vers docker login.

La prochaine étape est la construction et l'image. Je n'utiliserai que la dernière version, mais n'hésitez pas à
la taguer également si vous le souhaitez. Encore une fois, nous pouvons garder notre pipeline sans
configuration en utilisant la variable prédéfinie GitLab CI CI_REGISTRY_IMAGE.

Si vous n'êtes pas sûr de la valeur de ces variables, utilisez simplement echo $VARNAME pour inspecter
leur valeur. Il vaut mieux savoir exactement ce que vous faites au lieu de supposer.

- docker build -t $CI_REGISTRY_IMAGE .

260
7 - Intégration avec GitLab CI et registry

Nous pouvons ensuite envoyer l’image : docker push $CI_REGISTRY_IMAGE

Si toutes les commandes ont réussi, vous devriez bientôt voir l'image dans votre registre de conteneurs GitLab.

261
7 - Intégration avec GitLab CI et registry

262
7 - Intégration avec GitLab CI et registry
Comme je ne souhaite pas créer cette image à chaque validation, je vais configurer un calendrier de pipeline et
définir une règle qui garantira que ce travail ne s'exécute que selon le calendrier que je définis.

build image:
image: docker:20.10.10
services:
- docker:20.10.10-dind
rules:
- if: $CI_PIPELINE_SOURCE == "schedule"
script:
- echo $CI_REGISTRY_PASSWORD | docker login -u
$CI_REGISTRY_USER $CI_REGISTRY --password-stdin
- docker build -t $CI_REGISTRY_IMAGE .
- docker push $CI_REGISTRY_IMAGE

263
7 - Intégration avec GitLab CI et registry
Utilisation d'une image Docker du registre de conteneurs GitLab
dans un pipeline GitLab CI
C'est en fait plus facile que vous ne le pensez. Tout ce que vous devez savoir est le nom exact de l'image.
Accédez à votre registre de conteneurs et copiez le nom complet.

264
7 - Intégration avec GitLab CI et registry

Vous pouvez utiliser l'image dans le même projet ou dans d'autres projets. Un travail nécessitant l'image
Docker ressemblerait à ceci :

run tests:
image: registry.gitlab.com/somegroup/some-image-name
rules:
- if: $CI_PIPELINE_SOURCE != "schedule"
script:
- python --version
- pip --version
- pytest --version

265
8 - Orchestration avec Docker Swarm
Présentation
Les fonctionnalités de gestion de cluster et d'orchestration intégrées dans Docker Engine sont construites à l'aide de swarmkit . Swarmkit est un
projet distinct qui implémente la couche d'orchestration de Docker et est utilisé directement dans Docker.

Un swarm (essaim) se compose de plusieurs hôtes Docker qui s'exécutent en mode swarm et agissent en tant que gestionnaires (pour gérer
l'adhésion et la délégation) et de travailleurs (qui exécutent les services de swarm ). Un hôte Docker donné peut être un gestionnaire, un
travailleur ou remplir les deux rôles. Lorsque vous créez un service, vous définissez son état optimal (nombre de répliques, ressources réseau et
de stockage disponibles, ports que le service expose au monde extérieur, etc.). Docker s'efforce de maintenir cet état souhaité. Par exemple, si
un nœud de travail devient indisponible, Docker planifie les tâches de ce nœud sur d'autres nœuds. Une tâche est un conteneur en cours
d'exécution qui fait partie d'un service swarm et géré par un gestionnaire de swarm, par opposition à un conteneur autonome.

266
8 - Orchestration avec Docker Swarm
L'un des principaux avantages des services swarm par rapport aux conteneurs autonomes est que vous pouvez modifier la
configuration d'un service, y compris les réseaux et les volumes auxquels il est connecté, sans avoir à redémarrer manuellement le
service. Docker mettra à jour la configuration, arrêtera les tâches de service avec la configuration obsolète et en créera de nouvelles
correspondant à la configuration souhaitée.

Lorsque Docker s'exécute en mode swarm, vous pouvez toujours exécuter des conteneurs autonomes sur l'un des hôtes Docker
participant au swarm, ainsi que des services de swarm. Une différence clé entre les conteneurs autonomes et les services de swarm
est que seuls les gestionnaires de swarm peuvent gérer un swarm, tandis que les conteneurs autonomes peuvent être démarrés sur
n'importe quel daemon. Les daemons Docker peuvent participer à un swarm en tant que managers, workers ou les deux.

267
8 - Orchestration avec Docker Swarm

268
8 - Orchestration avec Docker Swarm
De la même manière que vous pouvez utiliser Docker Compose pour définir et exécuter des conteneurs, vous pouvez
définir et exécuter des piles de services Swarm .

Nodes
Un nœud est une instance du moteur Docker participant au swarm. Vous pouvez également considérer cela comme un
nœud Docker. Vous pouvez exécuter un ou plusieurs nœuds sur un seul ordinateur physique ou serveur cloud, mais les
déploiements de swarms de production incluent généralement des nœuds Docker répartis sur plusieurs machines
physiques et cloud.

Pour déployer votre application dans un swarm, vous soumettez une définition de service à un nœud de gestion
(manager) . Le manager distribue des unités de travail appelées tâches aux nœuds de travail (workers).

Les managers exécutent également les fonctions d'orchestration et de gestion de cluster requises pour maintenir l'état
souhaité du swarm. Les managers élisent un chef unique pour effectuer les tâches d'orchestration.

269
8 - Orchestration avec Docker Swarm
Les workers reçoivent et exécutent les tâches envoyées à partir des managers. Par défaut, les
managers exécutent également des services en tant que nœuds de travail, mais vous pouvez les
configurer pour exécuter des tâches de gestionnaire exclusivement et être des nœuds de gestionnaire
uniquement.

Un agent s'exécute sur chaque nœud de travail et rapporte les tâches qui lui sont affectées. Le worker
informe le manager de l'état actuel de ses tâches affectées afin que le gestionnaire puisse maintenir l'état
souhaité de chaque travailleur.

270
8 - Orchestration avec Docker Swarm
Service et tâches

Un service est la définition des tâches à exécuter sur les managers ou workers. C'est la structure centrale du
système de swarm et la racine principale de l'interaction de l'utilisateur avec le swarm.

Lorsque vous créez un service, vous spécifiez l'image de conteneur à utiliser et les commandes à exécuter dans
les conteneurs en cours d'exécution.

Dans le modèle de services répliqués , le gestionnaire de swarm distribue un nombre spécifique de tâches de
réplica entre les nœuds en fonction de l'échelle que vous avez définie dans l'état souhaité.

271
8 - Orchestration avec Docker Swarm
Pour les services globaux , le swarm exécute une tâche pour le service sur chaque nœud disponible dans le
cluster.

Une tâche contient un conteneur Docker et les commandes à exécuter à l'intérieur du conteneur. C'est l'unité
d'ordonnancement atomique de swarm. Les managers attribuent des tâches aux workersl en fonction du nombre
de répliques défini dans l'échelle de service. Une fois qu'une tâche est affectée à un nœud, elle ne peut pas se
déplacer vers un autre nœud. Il ne peut s'exécuter que sur le nœud assigné ou échouer.

272
8 - Orchestration avec Docker Swarm
Équilibrage de charge
Le gestionnaire de swarm utilise l'équilibrage de charge d'entrée pour exposer les services que vous souhaitez rendre
disponibles en externe au swarm. Le gestionnaire de swarm peut attribuer automatiquement au service un PublishedPort ou
vous pouvez configurer un PublishedPort pour le service. Vous pouvez spécifier n'importe quel port inutilisé. Si vous ne spécifiez
pas de port, le gestionnaire de swarm attribue au service un port dans la plage 30000-32767.

Les composants externes, tels que les équilibreurs de charge cloud, peuvent accéder au service sur le PublishedPort de n'importe
quel nœud du cluster, que le nœud exécute ou non actuellement la tâche pour le service. Tous les nœuds de l'essaim acheminent
les connexions d'entrée vers une instance de tâche en cours d'exécution.

Le mode Swarm a un composant DNS interne qui attribue automatiquement à chaque service de l'essaim une entrée DNS. Le
gestionnaire de swarm utilise l'équilibrage de charge interne pour répartir les demandes entre les services au sein du cluster en
fonction du nom DNS du service.

273
8 - Orchestration avec Docker Swarm

Algorithme de consensus distribué Raft


Raft est un algorithme de consensus distribué. Il a été conçu pour être facilement
compris. Il résout le problème consistant à faire en sorte que plusieurs serveurs se
mettent d'accord sur un état partagé même en cas de défaillance.

L'état partagé est généralement une structure de données prise en charge par un
journal répliqué. Nous avons besoin que le système soit pleinement opérationnel tant
que la majorité des serveurs sont opérationnels.

274
8 - Orchestration avec Docker Swarm

Raft fonctionne en élisant un leader dans le cluster. Le leader est responsable de


l'acceptation des demandes des clients et de la gestion de la réplication du journal vers
d'autres serveurs. Les données ne circulent que dans un seul sens : du leader vers les
autres serveurs.

275
8 - Orchestration avec Docker Swarm

Raft décompose le consensus en trois sous-problèmes :

● Élection du chef : Un nouveau chef doit être élu en cas d'échec d'un chef existant.
● Réplication des journaux : le leader doit synchroniser les journaux de tous les serveurs
avec les siens grâce à la réplication.
● Sécurité : si l'un des serveurs a validé une entrée de journal à un index particulier,
aucun autre serveur ne peut appliquer une entrée de journal différente pour cet index

276
8 - Orchestration avec Docker Swarm

Bases :
Chaque serveur existe dans l'un des trois états : leader, follower ou candidate.

277
8 - Orchestration avec Docker Swarm

En fonctionnement normal, il y a exactement un leader et tous les autres serveurs sont


des suiveurs. Les suiveurs sont passifs : ils n'émettent aucune demande par eux-mêmes
mais répondent simplement aux demandes des dirigeants et des candidats.

Le leader gère toutes les demandes des clients (si un client contacte un suiveur, le
suiveur le redirige vers le leader). Le troisième État, candidat, est utilisé pour élire un
nouveau chef.

278
8 - Orchestration avec Docker Swarm

Raft divise le temps en termes de durée arbitraire, chacun commençant par une
élection. Si un candidat remporte l'élection, il reste leader pour le reste du mandat. Si le
vote est divisé, ce mandat se termine sans chef.

Le nombre de termes augmente de façon monotone. Chaque serveur stocke le numéro


de terme actuel qui est également échangé dans chaque communication.

279
8 - Orchestration avec Docker Swarm

Élection du chef
Le leader envoie périodiquement un battement de cœur à ses partisans pour maintenir l'autorité. Une élection de leader est déclenchée
lorsqu'un suiveur expire après avoir attendu un battement de cœur du leader. Ce suiveur passe à l'état candidat et incrémente son
numéro de terme . Après avoir voté pour lui-même, il émet des RequestVotes RPC en parallèle avec les autres membres du cluster.
Trois issues sont possibles :

1. Le candidat reçoit les votes de la majorité des serveurs et devient le leader. Il envoie ensuite un message de pulsation aux
autres membres du cluster pour établir l'autorité.
2. Si d'autres candidats reçoivent AppendEntries RPC, ils vérifient le numéro du trimestre. Si le nombre de termes est
supérieur au leur, ils acceptent le serveur comme leader et reviennent à l'état de suiveur. Si le nombre de mandats est plus
petit, ils rejettent le RPC et restent toujours candidats.
3. Le candidat ne perd ni ne gagne. Si plus d'un serveur devient candidat en même temps, le vote peut être divisé sans majorité
claire. Dans ce cas, une nouvelle élection commence après l'expiration du délai d'un des candidats

280
8 - Orchestration avec Docker Swarm

Sécurité:

Raft s'assure que le leader d'un terme a validé les entrées de tous les termes précédents
dans son journal. Cela est nécessaire pour garantir que tous les journaux sont cohérents et
que les machines d'état exécutent le même ensemble de commandes.

Lors d'une élection de chef, le RPC RequestVote inclut des informations sur le journal du
candidat. Si l'électeur trouve que son journal est plus à jour que le candidat, il ne vote pas
pour lui.

281
8 - Orchestration avec Docker Swarm

Adhésion au cluster :

Pour que le mécanisme de changement de configuration soit sûr, il ne doit y avoir aucun moment
pendant la transition où il est possible que deux dirigeants soient élus pour le même mandat.

Raft utilise une approche en deux phases pour modifier l'appartenance au cluster. Tout d'abord, il
bascule vers une configuration intermédiaire appelée consensus conjoint. Puis, une fois celui-ci
validé, il bascule dans la nouvelle configuration.

282
8 - Orchestration avec Docker Swarm

Adhésion au cluster :

Lorsqu'un leader reçoit un message de changement de configuration, il stocke et réplique l'entrée


pour le consensus de jointure C<ancien, nouveau >. Un serveur utilise toujours la dernière
configuration de son journal pour prendre des décisions même s'il n'est pas validé. Lorsqu'un
consensus conjoint est engagé, seuls les serveurs avec C< ancien, nouveau> dans leurs journaux
peuvent devenir des leaders.

Voici une excellente présentation dynamique de cet algo : http://thesecretlivesofdata.com/raft/

283
8 - Orchestration avec Docker Swarm

Routing Mesh

Basiquement, le principe est le suivant : si vous avez un ensemble de containers


gérés par Swarm, par exemple, 4 containers : 3 pour le front et 1 pour la
database.

Quelque soit l’ip appelée (ex le container 2 appelé), si le port exposé est le même
que celui des 2 autres, Swarm gérera automatiquement l’appel de ces 3
containers avec cette même IP appelée et permettra l’affichage du front.
Comme une sorte de load balancer.

284
Routing Mesh
8 - Orchestration avec Docker Swarm

Si un appel sur
l’IP du node 4 ⇒
rediriger vers un
des containers
dont le port
correspondant
est exposé

285
8 - Orchestration avec Docker Swarm
Routing Mesh

https://docs.docker.com/engine/swarm/ingress/

Pour que ce système fonctionne depuis l’extérieur, il vous faut garder des
ports ouverts par votre firewall.

286
8 - Orchestration avec Docker Swarm
Exemple de déploiement d’une stack :

Une stack est un ensemble cohérent de services répartis dans des


containers, et dans notre cas gérés par docker swarm.

→ très proche de docker compose (sauf le build de l’image)

→ Manager est responsable du déploiement des services

287
8 - Orchestration avec Docker Swarm
Exemple de déploiement d’une stack :

docker stack deploy -c docker-compose.yml myapp

L’application contient 5 fichiers :

1. docker-compose : orchestration
2. Dockerfile : créer une image applicative
3. appl.py
4. requirements.txt
5. script shell de test

288
8 - Orchestration avec Docker Swarm
Exemple de déploiement d’une stack : version: '3'
services:
C’est une application python flask avec un app:
#build: .
serveur web et une BDD redis sur le port 5000 image: flask-redis:1.0
avec réception html de GET/POST. environment:
- FLASK_ENV=development
ports:
Voici le docker-compose.yml
- 5000:5000
redis:
image: redis:4.0.11-alpine

289
8 - Orchestration avec Docker Swarm
Exemple de déploiement d’une stack :

Le Dockerfile : FROM python:3.7.0-alpine3.8


WORKDIR /usr/src/app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
ENV FLASK_APP=app.py
CMD flask run --host=0.0.0.0

flask
Le requirements.txt : redis

290
8 - Orchestration avec Docker Swarm
Exemple de déploiement d’une stack :

Maintenant que nous avons vu le code, nous allons nous connecter au site play
with docker et lancer trois instances (1 manager et trois workers) :
https://labs.play-with-docker.com/

Se connecter en ssh aux trois nodes. Pour cela, vérifier si vous avez votre clé
ssh enregistrée en /var/root/.ssh/id_rsa

291
8 - Orchestration avec Docker Swarm
Exemple de déploiement d’une stack :

Nous allons initier un cluster swarm dans le node 3 manager :

docker swarm init --advertise-addr <ip_node3>

Il vous génère une commande avec un token que nous allons utiliser dans les
deux autres workers.
docker swarm join --token
SWMTKN-1-63ca1zb2g0wp139zmr0sanp9coo5bd2zpy6h1mjsudhurenjdl-2cax4e510f44l2ixhaxcqwl2m 192.168.0.6:2377

292
8 - Orchestration avec Docker Swarm
Exemple de déploiement d’une stack :

Dans le node 3 master : docker node ls

Il nous faut maintenant envoyer tous nos fichier vers le master :

scp -r <adresse_fichier> <connexion ssh (sans le mot ssh)>:~

Vérifier avec un ls dans le node 3

293
8 - Orchestration avec Docker Swarm
Exemple de déploiement d’une stack :

On peut plus faire le build avec le docker-compose. Donc nous devons vérifier que la ligne du
build dans le docker-compose est commentée.

Puis nous buildons l’image directement. docker build -t flask-redis:1.0 .

Ensuite nous déployons l’app et la BDD. docker stack deploy -c docker-compose.yml myapp

Puis vérifions avec docker service ls

294
8 - Orchestration avec Docker Swarm
Exemple de déploiement d’une stack :

Dans le docker play labs sur le node 3, nous pouvons observer un nouveau bouton qui
montre une écoute sur le port 80.

Pour tester l’app, nous allons lancer le script de test pour injecter

des éléments dans la db. ./post-get.sh

Maintenant nous pouvons tester le visualiseur pour voir où notre manager a mis en place
ces éléments.
docker run -it -d -p 8080:8080 -v /var/run/docker.sock:/var/run/docker.sock dockersamples/visualizer

295
8 - Orchestration avec Docker Swarm
Exemple de déploiement d’une stack :

Attention le visualiseur ne doit être installé uniquement que sur un manager. On constate
que le manager peut être capricieux et ne pas utiliser les workers qui sont à sa disposition.

296
8 - Orchestration avec Docker Swarm
Comment monitorer un swarm avec Prometheus et Grafana ?

Prometheus collecte des métriques de type gauge et counter. Pour cela il a besoin
qu’un exporter, qui exposera une route avec ces métriques, soit installé sur le
système à monitorer.

297
8 - Orchestration avec Docker Swarm

298
8 - Orchestration avec Docker Swarm
Comment monitorer un swarm avec Prometheus et Grafana ?

un exemple de métrique disponibles nativement sur Prometheus.

299
8 - Orchestration avec Docker Swarm
Comment monitorer un swarm avec Prometheus et Grafana ?

https://sbcode.net/prometheus/example-queries/

Cependant, vérifier et surveiller nos paramètres reste très lourd. Nous devons utiliser

le PromQL dont les regex utilisent la syntaxe RE2.

Nous pouvons alors y associer grafana qui à l’aide d’un dashboard en le connectant directement à notre prometheus .

https://grafana.com/grafana/dashboards/609

Il nous reste une étape : comment installer notre exporter sur swarm qui exposera une route avec toutes nos métriques?

300
8 - Orchestration avec Docker Swarm
Nous allons tester un exemple de docker-compose comportant une stack
wordpress-mysql-phpmyadmin avec deux autres containers prometheus et grafana.

Remarque : faites attention à l’emplacement du fichier de configuration de


prometheus qu’il n’entre pas en conflit avec un prometheus local.

301
8 - Orchestration avec Docker Swarm
Créer un dossier /wordpress et y créer les 6 fichiers de
volumes :

Modifier les adresses de volumes pour qu’elles


correspondent à votre machine. Ajouter la config de
prometheus dans le volume srv/wordpress/prometheus
pour ajouter traefik.

302
8 - Orchestration avec Docker Swarm

303
8 - Orchestration avec Docker Swarm
Maintenant nous pouvons lancer notre docker-compose
docker-compose up -d

Vérifier le wordpress en allant en localhost sur le port 8000, tout comme php et les
autres éléments.
Créer le blog wordpress et se connecter au phpmyadmin (wordpress:wordpress) pour vérifier sa
connection au mysql

Créons un article sur le blog.

304
8 - Orchestration avec Docker Swarm
Aller sur le dashboard de traefik : 127.0.0.1:8080/dashboard

305
8 - Orchestration avec Docker Swarm
Aller sur le dashboard de traefik : 127.0.0.1:8080/metrics pour vérifier la route que
va scraper prometheus
Aller sur prometheus en 9090, et vérifier ses targets

Puis plugger grafana sur notre prometheus

2 TP sur Docker Swarm : Initiation avec le didacticiel Swarm et mise en place d’un Swarm monitore un
cluster de monnaie virtuelle

306
9 - Administration des conteneurs
Cycle de vie des
containers :

l’idée de base est


qu’un container est fait
pour être lancé,
détruit, relancé,
modifié, stoppé…

307
9 - Administration des containers
Cycle de vie des containers :
Pour créer un container : $ docker create --name <nom du conteneur> <nom de l'image>

Pour démarrer un container arrêté : $ docker start <nom du conteneur>

Pour le lancer : cette commande compile les deux précédentes en une

$ docker run -it --name <nom du conteneur> <nom de l'image>

308
9 - Administration des containers

Pour mettre les processus dans le container en pause : $ docker pause <nom du conteneur>

Pour le réactiver : $ docker unpause <nom du conteneur>

L'arrêt d'un conteneur en cours d'exécution signifie l'arrêt de tous les processus en cours d'exécution
dans ce conteneur. Arrêter ne signifie pas tuer ou mettre fin au processus.

$ docker stop <nom du conteneur>

309
9 - Administration des containers

Pour arrêter tous les conteneurs en cours d'exécution, nous pouvons utiliser la commande suivante :

$ docker stop $(docker container ls -aq)

La suppression du conteneur signifie la destruction de tous les processus exécutés à l'intérieur du


conteneur, puis la suppression du conteneur. Il est préférable de détruire le conteneur, uniquement s'il
est présent à l'état arrêté au lieu de détruire de force le conteneur en cours d'exécution.

$ docker stop <nom du conteneur>

$ docker rm <nom du conteneur>


310
9 - Administration des containers

Un conteneur arrêté peut passer à l'état de démarrage, ce qui signifie que tous les processus à
l'intérieur du conteneur redémarreront. Lorsque nous exécutons la commande docker stop, le
processus principal à l'intérieur du conteneur reçoit un signal SIGTERM

Il est également possible de supprimer tous les containers en une seule commande :

$ docker rm $(docker ps -aq)

Tuer un container : $ docker kill <nom du conteneur>

311
9 - Administration des containers
les commandes docker stop et docker kill présentent les différences suivantes :

1. docker stop tente d'arrêter normalement le(s) conteneur(s) pendant que docker kill(par défaut) les
arrête/termine immédiatement ;
2. docker stop émet un signal SIGTERM au processus principal à l'intérieur du conteneur, tandis
que docker kill (par défaut) émet un signal SIGKILL;
3. Avec docker kill, vous pouvez spécifier d'envoyer un signal différent (au processus principal à
l'intérieur du conteneur) que le signal par défaut SIGKILL, en utilisant l’option --signal. La même
chose n'est pas possible avec la commande docker stop;
4. Avec docker stop, le ou les conteneurs doivent se conformer à la demande d'arrêt dans un délai
(configurable) (qui est par défaut 10 secondes), après quoi il essaie de force de tuer le conteneur.
docker kill n'a pas de tel délai d'attente.

312
9 - Administration des containers

1. La commande Docker create crée un nouveau conteneur à partir de l'image spécifiée.


Cependant, il n'exécutera pas le conteneur immédiatement.
2. La commande Docker start est utilisée pour démarrer tout conteneur arrêté. Si nous avons
utilisé le docker pour créer une commande pour créer un conteneur, nous pouvons le démarrer
avec cette commande.
3. La commande d'exécution run de Docker est une combinaison de création et de démarrage
car elle crée un nouveau conteneur et le démarre immédiatement. En fait, la commande docker
run peut même extraire une image de Docker Hub si elle ne trouve pas l'image mentionnée sur
votre système.

313
9 - Administration des conteneurs
Analyse des logs

La commande docker logs affiche les informations enregistrées par un conteneur en cours
d'exécution. La commande docker service logs affiche les informations enregistrées par tous les
conteneurs participer à un service. Les informations enregistrées et le format des log dépend
presque entièrement de la commande de point de terminaison du conteneur.

Par défaut, docker logs montre la commande STDOUT et STDERR

Il est possible que votre image exécute un processus non interactif tel qu'un serveur Web ou un
base de données, cette application peut envoyer sa sortie aux fichiers journaux au lieu de STDOUT
et STDERR.

314
9 - Administration des conteneurs
L'image officielle nginx crée un lien symbolique à partir de
/var/log/nginx/access.log à /dev/stdout, et crée un autre lien symbolique à partir
de /var/log/nginx/error.log à /dev/stderr, en écrasant les fichiers journaux et
provoquant l'envoi des journaux à l'appareil spécial approprié à la place. Voici le
Dockerfile illustrant cela :

https://github.com/nginxinc/docker-nginx/blob/8921999083def7ba43a06fabd5f
80e4406651353/mainline/jessie/Dockerfile

315
9 - Administration des conteneurs
Le réseau dans Docker

Nous avons déjà abordé le réseau dans Docker avec le docker-compose. Nous
allons répertorier les différents types de networking.

316
9 - Administration des conteneurs
● Les réseaux bridge définis par l'utilisateur sont les meilleurs lorsque vous avez
besoin de plusieurs conteneurs pour communiquer sur le même hôte Docker.
● Les réseaux host sont les meilleurs lorsque la pile réseau ne doit pas être isolée de
l'hôte Docker, mais vous souhaitez isoler d'autres aspects du conteneur.
● Les réseaux overlay sont les meilleurs lorsque vous avez besoin de conteneurs
s'exécutant sur différents hôtes Docker pour communiquer, ou lorsque plusieurs
applications fonctionnent ensemble en utilisant des services swarm.
● Les réseaux Macvlan sont les meilleurs lorsque vous migrez à partir d'une
configuration de machine virtuelle ou vous avez besoin que vos conteneurs
ressemblent à des hôtes physiques sur votre réseau, chacun avec un adresse MAC
unique.

317
9 - Administration des conteneurs
Pour automatiser le démarrage des containers au boot, il faut pour cela creuser les
policies qui ont été annexées au container :

Ce lien dans la documentation montre différentes solutions. Docker recommande


principalement d’utiliser la ligne de commande.

Il faut avant tout lancer le service dockerd au démarrage.

sudo systemctl enable docker

318
9 - Administration des conteneurs

Ensuite, si vous avez un fichier docker-compose .yml, ajoutez restart: always ou si vous avez un
conteneur docker, ajoutez restart=always comme ceci :

docker run --restart=always

Attention: Si vous arrêtez manuellement un conteneur, sa stratégie de redémarrage est ignorée jusqu'à
ce que le daemon Docker redémarre ou que le conteneur soit redémarré manuellement.
Si vous voulez démarrer docker-compose, tous les services s'exécutent lorsque vous redémarrez votre
système. Vous n'exécutez donc la commande ci-dessous qu'une seule fois

$ docker-compose up -d

319
9 - Administration des conteneurs
# /etc/systemd/system/docker-compose-app.service

Si maintenant vous désirez [Unit]


directement lancer un docker Description=Docker Compose Application Service
compose depuis le boot de PC, il va Requires=docker.service
falloir créer un service qui appelera le After=docker.service
binaire docker compose avec les
paramètres nécessaires : [Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/srv/docker
systemctl enable ExecStart=/usr/local/bin/docker-compose up -d
docker-compose-app ExecStop=/usr/local/bin/docker-compose down
TimeoutStartSec=0

[Install]
WantedBy=multi-user.target
320
10 - Docker Machine

https://docs.docker.com/machine/

321
11 - Stockage

Pour le stockage, nous avons déjà vu le montage des volumes et des bind
mounts.

Nous allons ici voir une 3e possibilité avec les storage drivers.

Ressources parallèles : à propos des pilotes de stockage

322
11 - Stockage

Il existe sur cette page de la doc Docker,


https://docs.docker.com/engine/reference/commandline/run/ , une option du run qui
permet de gérer le storage driver :

C’est une option également disponible dans le docker-compose : --storage-opt

https://docs.docker.com/compose/compose-file/compose-file-v2/

323
11 - Stockage
File storage vs Block Storage vs Object Storage in container ?

File Storage : stockage du système de fichiers

L'idée derrière la persistance basée sur l'hôte est vraiment simple. Les conteneurs résident sur un serveur hôte. Ce
serveur hôte contient son propre système d'exploitation, et son propre système de fichiers. Les conteneurs peuvent être
configurés pour stocker données persistantes dans un dossier dédié sur le fichier du serveur hôte.

Les conteneurs Docker utilisent normalement un système de fichiers union pour assembler les couches de conteneurs
dans une structure de fichier cohésive. Basé sur l'hôte la persistance contourne le système de fichiers de l'union pour les
données qui doivent être stocké de manière persistante et stocke ces données en utilisant le même système de fichiers
qui est en cours d'utilisation sur l'hôte. Le principal problème causé par la persistance sur l'hôte simple est qu'il sape
complètement la portabilité des conteneurs. Lorsque la persistance de l'hôte est utilisée, une ressource de dépendance
(le stockage persistant) réside à l'extérieur du conteneur, sur le fichier natif du serveur hôte système. Pour contourner ce
problème, d'autres variantes de la persistance de l'hôte ont été créées. Par exemple, la persistance multi-hôte utilise un
système de fichiers distribué pour répliquer le stockage persistant sur plusieurs serveurs hôtes.

324
11 - Stockage

File Storage : stockage du système de fichiers


Le stockage du système de fichiers est probablement la correspondance la plus
délicate pour les conteneurs car les systèmes de fichiers n'étaient pas conçu à
l'origine avec la portabilité à l'esprit.
Block Storage
Le stockage par blocs stocke des morceaux de données dans des blocs. Un bloc n'est
identifié que par son adresse. Un bloc n'a pas de nom de fichier, ni ses propres
métadonnées. Les blocs ne deviennent significatifs que lorsqu'ils sont combinés avec
d'autres blocs pour former une donnée complète.

325
11 - Stockage

Le stockage par blocs est couramment utilisé pour les applications de base de données en
raison de sa performance. Le stockage par blocs est également généralement utilisé pour
fournir capacités de capture d'instantanés, qui permettent à un volume d'être restauré vers
un moment précis, sans avoir à restaurer une sauvegarde.
Dans le cas de conteneurs, le stockage en bloc est parfois mis en œuvre sous forme de
stockage défini par conteneur. Le stockage défini par conteneur est une forme de stockage
défini par logiciel, mais est spécifiquement destiné à être utilisé dans un environnement
conteneurisé. Ce stockage est souvent implémenté à l'intérieur d'un conteneur de stockage
dédié. Le seul grand défi est de s'assurer que le stockage en bloc les données sont
disponibles dans un environnement composé de plusieurs hôtes

326
11 - Stockage
Le stockage d'objets fonctionne différemment du stockage ou du bloc de système de fichiers stockage. Plutôt que de
référencer des données par une adresse de bloc ou un nom de fichier, les données sont stockées en tant qu'objet et sont
référencées par un ID d'objet. le les avantages du stockage objet sont qu'il est massivement évolutif et permet une grande
flexibilité quant à l'association attributs avec des objets. L'inconvénient de l'utilisation du stockage d'objets est qu'il ne
fonctionne pas aussi bien que le stockage en bloc. Parce que l'objet le stockage est conçu principalement pour l'évolutivité,
c'est un choix populaire pour les fournisseurs de cloud public.

Les conteneurs Docker peuvent être liés à un objet stockage sur Amazon Web Services ou Microsoft Azure, mais cela
nécessite que l'application conteneurisée soit spécifiquement conçue pour prendre avantage du stockage d'objets. Alors
qu'une application typique peut être conçu pour accéder aux données via un système de fichiers ou des appels SCSI, objet
le stockage nécessite des appels REST basés sur HTTP tels que Get ou Put. En tant que tel, le stockage d'objets doit
généralement être sauvegardé pour les applications qui ont besoin stockage à grande échelle ou stockage qui doit
traverser des zones géographiques les frontières. Le point à retenir : [Le stockage d'objets peut être plus complexe à
implémenter car il repose sur des appels REST, mais l'évolutivité qui le stockage d'objets en fait un bon choix pour
les conteneurs environnements où l'évolutivité massive est une priorité.]

327
11 - Stockage
La question qui se pose donc : comment gérer ces différents stockages à différents
endroits pour nos containers ?

328
11 - Stockage
Il existe plusieurs possibilités notamment pour Swarm et Kubernetes.

Par exemple, les bases de données ont besoin d'une approche sans partage. Un
nouveau conteneur doit avoir ses propres fichiers de base de données dans son
propre espace et répliquer les données via les installations de réplication de la base
de données.

Selon la doc de docker, il existe plusieurs driver de stockage dans les containers :

https://docs.docker.com/storage/storagedriver/select-storage-driver/

329
11 - Stockage
Nous allons maintenant découvrir un plugin de volume Docker. Il permet à Docker d’activer des
volumes sur plusieurs hôtes Docker;
Il existe également des plugins de réseau.
https://docs.docker.com/engine/extend/legacy_plugins/
Nous allons nous intéresser au plugin Rex-Ray qui fournit un moteur d'orchestration du stockage
indépendant du fournisseur. L'objectif primaire de conception est de fournir un stockage persistant
pour Docker, Kubernetes, et Mesos.

Il est également disponible sous forme de package Go, d'outil CLI et de service Linux qui lui permet
d'être utilisé pour des cas d'utilisation supplémentaires.

330
11 - Stockage
Quand nous observons sur Docker Hub, quels sont les 10 images les plus chargées,
nous voyons qu’elles ont besoin de data persistantes.

Quand nous cliquons sur une image, nous avons la possibilité de voir quel volume
elle utilise, ou aussi comment lui régler une conf avec un Dockerfile par exemple
avec redis: https://hub.docker.com/_/redis

Cependant, un autre problème est soulevé ⇒ la très grande majorité de nos


applications nécessitent des data persistantes, mais sous formes différentes avec
des requêtes de partenaires différents.

331
11 - Stockage
De plus, même si nous utilisons des volumes, si nous perdons le serveur les
contenant nous aurons également perdu ces données…

Nous avons besoin d’une orchestration de stockage des données pour containers
permettant cette persistance via le cloud aussi.

⇒ https://rexray.readthedocs.io/en/stable/

Nous avons besoin de produire des volumes, de les attacher, de les détacher…

332
11 - Stockage
Il est possible par exemple qu’un container sur un hôte ait un volume qui lui soit attaché.

Si ce container tombe, nous devons en lancer un autre derrière et le rattacher à ce même


volume, que ce nouveau container soit sur le même hôte ou non.

Rex-ray donc :

➔ offre un stockage sur différentes plate-formes


➔ permet de rendre ce stockage agnostique : fonctionne quelquesoit le type de stockage
➔ s’installe comme un simple binaire ou déployé comme un container
➔ permet de gérer une architecture décentralisée

333
11 - Stockage
Imaginons que vous ayez un millier de containers sur AWS et vous avez besoin
d’utiliser les volumes EBS. Comment allez-vous fournir votre access key, ou votre
IAM profiles ?

On pourrait les mettre dans les fichiers de config des containers mais au final nous
aurions nos infos précieuses réparties sur des milliers de nodes…

Rex-ray gère cela avec un controller qui contiendra vos credentials.

334
11 - Stockage
Ceph

C’est une solution de disk storage qui permet un stockage “sans fin”. Vous branchez
un disque de stockage et il pourra par la suite être distribué entre différents
terminaux.

Il permet également de déployer des configurations avec Ansible sur du bare metal

335
11 - Stockage

336
11 - Stockage
Il permet de jouer différents scripts Ansible et de les organiser.

337
12 - Sécurité

Pourquoi se soucier de la sécurité sur Docker alors que nous avons été obligé de passer en root pour
nos commandes ?

Voici un exemple de commande dangereuse qui fonctionne sans root :

docker run --donotrunme -v /sbin:/sbin busybox rm -rf /sbin

Elle efface tous les binaires dans votre machine hôte !

338
12 - Sécurité

La commande suivante montre le contenu du fichier shadow password de


l’hôte

docker run -v /etc/shadow:/etc/shadow busybox cat /etc/shadow

339
12 - Sécurité

Diverses mesures ont déjà été prises par les responsables de Docker pour réduire les risques de sécurité
liés à l'exécution de conteneurs. Par exemple, certains points de montage principaux (tels que /proc et /sys)
sont désormais montés en lecture seule.

Les capacités Linux par défaut ont été réduites.

La prise en charge des systèmes de sécurité tiers tels que SELinux et AppArmor existe désormais.

Nous allons voir plus en détail ces éléments et certaines des mesures que vous pouvez prendre pour
réduire les risques d'exécuter des conteneurs sur votre système.

340
12 - Sécurité

Dans une tentative de prise en charge d’une approche plus fine de la gestion des utilisateurs privilégiés, les
ingénieurs du noyau Linux ont développé des capacités. Il s'agissait d'une tentative de décomposer le
privilège root monolithique en tranches de fonctionnalités qui pourraient être accordées discrètement.
Vous pouvez en savoir plus à leur sujet en exécutant les capacités de man 7 capabilities (en supposant que la
page de manuel soit installée).

Docker a gentiment désactivé certaines fonctionnalités par défaut. Cela signifie que même si vous avez root
dans le conteneur, il y a des choses que vous ne pourrez pas faire. Par exemple, la capacité
CAP_NET_ADMIN, qui vous permet d'affecter la pile réseau de l'hôte, est désactivée par défaut.

Ce tableau répertorie les capacités Linux, donne une brève description de ce qu'elles autorisent et indique
si elles sont autorisées par défaut dans les conteneurs Docker

341
12 - Sécurité

342
12 - Sécurité

343
12 - Sécurité
Malheureusement, les mainteneurs du noyau n'ont alloué que 32 capacités au sein du système, de sorte
que les capacités ont augmenté au fur et à mesure que de plus en plus de privilèges root affinés ont été
extraits du noyau. Plus particulièrement, la capacité CAP_SYS_ADMIN vaguement nommée couvre des
actions aussi variées que la modification du nom de domaine de l'hôte pour dépasser la limite du nombre
de fichiers ouverts à l'échelle du système.

Une approche extrême consiste à supprimer toutes les fonctionnalités activées par défaut dans Docker du
conteneur et à voir ce qui cesse de fonctionner. Ici, nous démarrons un shell bash avec les fonctionnalités
activées par défaut supprimées :
$ docker run -ti --cap-drop=CHOWN --cap-drop=DAC_OVERRIDE \
--cap-drop=FSETID --cap-drop=FOWNER --cap-drop=KILL --cap-drop=MKNOD \
--cap-drop=NET_RAW --cap-drop=SETGID --cap-drop=SETUID \
--cap-drop=SETFCAP --cap-drop=SETPCAP --cap-drop=NET_BIND_SERVICE \

--cap-drop=SYS_CHROOT --cap-drop=AUDIT_WRITE debian /bin/bash

344
12 - Sécurité

Les éléments de sécurité avec Docker


Voici avant tout les recommandations de la fondation OWASP : Open Source Foundation for Application
Security pour Docker : https://cheatsheetseries.owasp.org/cheatsheets/Docker_Security_Cheat_Sheet.html

Nous allons nous concentrer sur la règle 6 : Utiliser le Linux Security Module avec SELinux

Pour son installation sur Debian : https://wiki.debian.org/SELinux/Setup

345
12 - Sécurité
Qu'est-ce que SELinux et comment SELinux est utilisé dans Docker ?

Il existe trois solutions courantes pour implémenter le contrôle d'accès sous Linux :

1. SELinux
2. AppArmor
3. GrSecurity

Security-Enhanced Linux (SELinux) est un module de sécurité du noyau Linux qui fournit un mécanisme de
prise en charge des politiques de sécurité de contrôle d'accès. C'est une fonction de sécurité du noyau Linux. Il
est conçu pour protéger le serveur contre les erreurs de configuration et/ou les daemons compromis. Il met des
limites et indique aux daemons ou programmes du serveur à quels fichiers ils peuvent accéder et quelles
actions ils peuvent entreprendre en définissant une politique de sécurité.

346
12 - Sécurité
SELinux est une implémentation d'un mécanisme de sécurité MAC. MAC est l'acronyme de Mandatory Access
Control (MAC). Il est intégré au noyau Linux et activé par défaut sur Fedora, CentOS, RHEL et quelques autres
distributions Linux. SELinux permet à l'administrateur du serveur de définir diverses autorisations pour tous les
processus. Il définit comment tous les processus peuvent interagir avec d'autres parties du serveur telles que :

● Pipes
● Files
● Network ports
● Sockets
● Directories
● Other process

347
12 - Sécurité
SELinux impose des restrictions sur chacun des objets ci-dessus selon une politique. Par exemple, un utilisateur
Apache avec une autorisation complète ne peut accéder qu'au répertoire /var/www/html, mais ne peut pas
toucher à d'autres parties du système telles que le répertoire /etc sans modification de stratégie.

Si un attaquant réussissait à accéder à sendmail mail ou à bind DNS ou au serveur Web Apache, il n'aurait accès
qu'au serveur exploité et aux fichiers comme défini dans la politique du serveur. Un attaquant ne peut pas
accéder aux autres parties du système ou au LAN interne. En d'autres termes, les dommages peuvent
désormais être limités au serveur et aux fichiers particuliers. Le cracker ne pourra pas obtenir de shell sur votre
serveur via des daemons communs tels que Apache / BIND / Sendmail car SELinux offre les fonctionnalités de
sécurité suivantes :

348
12 - Sécurité
● Protégez les données des utilisateurs contre les accès non autorisés.
● Protégez les autres daemons ou programmes des accès non autorisés.
● Protégez les ports / sockets / fichiers réseau contre les accès non autorisés.
● Protégez le serveur contre les exploits.
● Évitez l'escalade de privilèges et bien plus encore.

Veuillez noter que SELinux n'est pas une solution miracle pour protéger le serveur. Vous devez suivre d'autres
pratiques de sécurité telles que

● Implémentation de la politique de pare-feu.


● Surveillance du serveur.
● Patcher le système à temps.
● Écriture et sécurisation des scripts cgi/php/python/perl.

349
12 - Sécurité
Le fichier de configuration /etc/selinux/config contrôle si SELinux est activé ou désactivé, et s'il est activé, si SELinux fonctionne en
mode permissif ou en mode d'application.

CONFIGURATION DE SELINUX

SELinux est défini en trois modes.

Application – La politique de sécurité de SELinux est appliquée. SI cela est défini, SELinux est activé et essaiera d'appliquer
strictement les politiques de SELinux

Permissif – SELinux imprime des avertissements au lieu de les appliquer. Ce paramètre donnera simplement un avertissement
lorsqu'un paramètre de politique SELinux est violé

Désactivé – Aucune stratégie SELinux n'est chargée. Cela désactivera totalement les politiques SELinux.

350
12 - Sécurité
Politiques SELinux

SELinux permet d'installer plusieurs politiques sur le système, mais une seule politique peut être active à un
moment donné. À l'heure actuelle, il existe deux types de politique SELinux :

Ciblé – La politique ciblée est conçue comme une politique où la plupart des processus fonctionnent sans
restrictions, et seuls des services spécifiques sont placés dans des domaines de sécurité distincts qui sont
confinés par la politique.

Strict – La politique stricte est conçue comme une politique où tous les processus sont partitionnés dans des
domaines de sécurité à granularité fine et limités par la politique.

351
12 - Sécurité
Pour mettre SELinux en mode application : $ sudo setenforce 1

Pour interroger l’état de SELinux : $ getenforce

Pour voir le statut SELinux de manière simplifiée, vous pouvez utiliser sestatus : $ sestatus

Pour obtenir des informations détaillées sur les différents statuts de SELinux sur différents services, utilisez
l'option -b le long de sestatus : $ sestatus -b

Comment désactiver SElinux ?

352
12 - Sécurité
Comment désactiver SElinux ?

353
12 - Sécurité
Et comment le réactiver ?

354
12 - Sécurité
Comment utiliser SELinux avec Docker ?

L'interaction entre la politique SELinux et Docker est axée sur deux préoccupations : la protection de l'hôte et la protection
des conteneurs les uns par rapport aux autres.

Les étiquettes SELinux se composent de 4 parties :

Utilisateur : Rôle : Type : niveau.

SELinux contrôle l'accès aux processus par type et par niveau. Docker propose deux formes de protection SELinux :
l'application des types et la séparation de sécurité multi-catégorie (MCS).

Docker a l'indicateur -selinux-enabled par défaut dans CentOS 7.4.1708. Cependant, dans le cas où votre image ou votre
outil de gestion de configuration le désactive, comme ce fut le cas pour notre module marionnette vérifiez-le, vous vérifiez
en exécutant la commande suivante

355
12 - Sécurité
Attention :

The --mount flag does not support z or Z options for modifying selinux labels…

https://docs.docker.com/storage/bind-mounts/

$ docker info | grep 'Security Options'

more /etc/selinux/config

Voici un très bon lien pour s’exercer sur SELinux avec Docker : https://jaosorior.dev/2018/selinux-and-docker-notes/

356
12 - Sécurité
Nous avons également la possibilité de scanner nos images afin de checker leurs vulnérabilités :

https://docs.docker.com/engine/scan/

Docker utilise dans ce cas Snyk qui permet de détecter les vulnérabilités sur d’autres programmes ou systèmes

357
12 - Sécurité
Docker Content Trust (DCT)

Lors du transfert de données entre des systèmes en réseau, la confiance est une préoccupation centrale. En
particulier, lors de la communication sur un support non fiable tel qu'Internet, il est essentiel d’assurer l'intégrité et la
sécurité de l’édition de toutes les données d'un système. Vous utilisez le moteur Docker pour envoyer et extraire des
images (données) vers un registre public ou privé. Vérifier le contenu d’une image vous donne la possibilité de
vérifier à la fois l'intégrité et l'éditeur de toutes les données reçues d'un registre sur n'importe quel canal.

Docker Content Trust (DCT) offre la possibilité d'utiliser des signatures numériques pour données envoyées et
reçues des registres Docker distants. Ces signatures permettent la vérification côté client ou à l'exécution de
l'intégrité et de l'éditeur de balises d'images.

Grâce au DCT, les éditeurs d'images peuvent signer leurs images et les consommateurs d'images peuvent s'assurer
que les images qu'ils extraient sont signées. Les éditeurs peuvent être des particuliers ou des organisations signant
manuellement leur contenu ou leur fourniture automatisée de logiciels chaînes signant du contenu dans le cadre de
leur processus de publication.

358
12 - Sécurité
Un enregistrement d’image individuelle a l'identifiant suivant :

[REGISTRY_HOST[:REGISTRY_PORT]/]REPOSITORY[:TAG]

Une image peut avoir plusieurs balises. Par exemple, latest et 3.1.2 sont les deux balises. Un éditeur d'images
peut créer une image et la combinaison de balises changeant plusieurs fois l'image à chaque build.

Le DCT est associé à la partie TAG d'une image. Chaque référentiel d'images a un ensemble de clés que les
éditeurs d'images utilisent pour signer une balise d'image à la discrétion des éditeurs.

Un référentiel d'images peut contenir une image avec une balise signée et une autre étiquette qui ne l'est
pas. L'étiquette latest peut être non signée alors que l'étiquette 3.1.6 pourrait être signée. C'est la
responsabilité de l'éditeur d'image de décider si une balise d'image doit être signée ou non.

359
12 - Sécurité

Dans cette représentation,


certaines balises d'images sont
signées, d'autres non :

360
12 - Sécurité

Les consommateurs d'images peuvent activer DCT pour s'assurer que les images qu'ils utilisent
sont signées. Si un consommateur active DCT, ils ne peuvent extraire, exécuter ou construire
qu'avec des images de confiance. L'activation de la DCT, c'est un peu comme appliquer un «
filtre » à votre registre. Les consommateurs « voient » seules les balises d'image signées et les
balises d'image non signées, moins souhaitables, sont « invisible » pour eux.

361
12 - Sécurité
Tandis que le consommateur qui n’a pas activé le DCT, rien ne change pour lui. Chaque image
est visible, qu’elle soit signée ou non.

Clés de confiance du contenu Docker

La confiance pour une étiquette d'image est gérée par l'utilisation de clés de signature. Un jeu
de clés est créé lorsqu'une opération utilisant DCT pour la première fois. Un jeu de clés se
compose des classes de clés suivantes :

● une clé hors ligne qui est la racine de DCT pour une balise d'image
● référentiel ou clés de balisage qui signent les balises
● clés gérées par le serveur telles que la clé d'horodatage, qui fournit de la fraîcheur des
garanties de sécurité pour votre référentiel

362
12 - Sécurité

La perte de la clé racine est très


difficile à récupérer. Corriger cette
perte nécessite l'intervention de
Docker Support pour la
réinitialisation de l'état du
référentiel. Cette perte nécessite
également une intervention
manuelle de chaque consommateur
qui a utilisé un tag de ce référentiel
avant la perte.

363
12 - Sécurité

Pour signer une image Docker, vous aurez besoin d'une paire de clés de délégation. Ces clés peut
être généré localement en utilisant $ docker trust key generate ou généré par une autorité de
certification.

Nous allons d'abord ajouter la clé privée de délégation dans le dépôt local Docker. (Par défaut, il est
stocké dans ~/.docker/trust/). Si vous générez des clés de délégation avec $ docker trust key
generate, la clé privée est automatiquement ajouté en local. Si vous importez une clé, vous devrez
utiliser la commande $ docker trust key load.

$ docker trust key generate my_key_docker

364
12 - Sécurité

Ou si vous avez déjà une clé :

$ docker trust key load key.pem --name my_local_key

Ensuite, nous devrons ajouter la clé publique de délégation au serveur Notary ; ceci est spécifique à
un référentiel d'images particulier dans le notaire connu sous le nom de Global Unique Name (GUN).
Si c'est la première fois que vous ajoutez une délégation à ce référentiel, cette commande lancera
également le référentiel, en utilisant une clé racine notaire locale.

365
12 - Sécurité

Ou si vous avez déjà une clé :

$ docker trust key load key.pem --name my_local_key

Ensuite, nous devrons ajouter la clé publique de délégation au serveur Notary ; ceci est spécifique à
un référentiel d'images particulier dans le notaire connu sous le nom de Global Unique Name (GUN).
Si c'est la première fois que vous ajoutez une délégation à ce référentiel, cette commande lancera
également le référentiel, en utilisant une clé racine notaire locale.

$ docker trust signer add --key cert.pem my_key_docker registry.example.com/admin/demo

366
12 - Sécurité

Enfin, nous utiliserons la clé privée de délégation pour signer une balise particulière et la pousser vers le
registre.

$ docker trust sign registry.example.com/admin/demo:1

Les données de confiance distantes pour une balise ou un référentiel peuvent être visualisées par la
commande $ docker trust inspect

$ docker trust inspect --pretty registry.example.com/admin/demo:1

Lancement TP DCT
367
12 - Sécurité

Les éléments de sécurité avec Docker


La plupart des images Docker sont exécutées en tant que conteneurs en appelant quelque chose du genre docker
run <image>:<tag>. Cependant, il est également possible - et souvent nécessaire pour des raisons de sécurité - de
s'exécuter en spécifiant également @sha256:<digest>. Mais qu'est-ce que cela fait réellement et quels vecteurs de
sécurité cela fournit-il réellement ?

Le démarrage des conteneurs Docker nécessite une image, qui est présentée au format [namespace/]<image-name> suivi d'une
balise :<tag-name>. Si aucune balise n'est spécifiée, latest est utilisé. Cette balise est un pointeur vers une image, un
ensemble de fichiers et de métadonnées que Docker peut utiliser pour exécuter un conteneur. Certaines images tombent sous
l'espace de noms racine, comme ubuntu

368
12 - Sécurité

Les éléments de sécurité avec Docker


Docker digest est fourni sous forme de hachage d'une image Docker prise en charge par le format de registre Docker v2. Ce hachage
sha256 est généré au fur et à mesure et est déterministe en fonction de la construction de l'image.

Cela signifie que tant que le Dockerfile et tous les composants de build (image de base sélectionnée dans FROM, tous les fichiers
téléchargés ou copiés dans l'image, etc.) sont inchangés entre les builds, l'image construite sera toujours résolue en le même condensé
(digest). Ceci est important car un changement dans le digest indique que quelque chose a changé dans l'image.

Les condensés des images extraites peuvent être répertoriés en exécutant docker images --digests

Remarque : uname -a, qui est couramment utilisé pour vérifier la version en cours d'exécution d'un hôte, ne fonctionnera pas à l'intérieur

des conteneurs car il rapporte en fonction du noyau en cours d'exécution, qui est partagé à partir du système d'exploitation hôte.

369
12 - Sécurité
Les éléments de sécurité avec Docker
$ docker run --rm ubuntu:20.04 /bin/bash -c "cat /etc/lsb-release"

$ docker run --rm ubuntu:16.04 /bin/bash -c "cat /etc/lsb-release"

Maintenant, réexécutons 20.04 avec une somme de contrôle (copiée à partir de la sortie docker images --digests ci - dessus) :

$ docker run --rm ubuntu:20.04@sha256:8bce67040cd0ae39e0beb55bcb976a824d9966d2ac8d2e4bf6119b45505cee64 /bin/bash -c "cat


/etc/lsb-release"

C’est ce que nous nous attendions à voir. Mais maintenant, copions plutôt le digest de l'image 16.04 :

$ docker run --rm ubuntu:20.04@sha256:db6697a61d5679b7ca69dbde3dad6be0d17064d5b6b0e9f7be8d456ebb337209 /bin/bash -c "cat


/etc/lsb-release"

370
12 - Sécurité
Les éléments de sécurité avec Docker
On peut même utiliser des balises qui n'existent pas :

$ docker run --rm ubuntu:tag-does-not-exist@sha256:db6697a61d5679b7ca69dbde3dad6be0d17064d5b6b0e9f7be8d456ebb337209


/bin/bash -c "cat /etc/lsb-release"
Et docker pull fonctionne même pour cette balise inexistante :

docker pull ubuntu:tag-does-not-exist@sha256:db6697a61d5679b7ca69dbde3dad6be0d17064d5b6b0e9f7be8d456ebb337209

Le digest est limité à l'espace de noms et au nom de l'image, donc ce qui suit ne fonctionne pas lors de l'extraction d'une image

inexistante même si ce condensé existe sur l'hôte Docker :

$ docker pull
not-an-image:tag-does-not-exist@sha256:db6697a61d5679b7ca69dbde3dad6be0d17064d5b6b0e9f7be8d456ebb337209

371
12 - Sécurité
Les éléments de sécurité avec Docker
Maintenant, nous voyons une balise 20.04, mais notre image est 16.04. Pourquoi ?

Lançons un processus inactif dans un nouveau conteneur :

docker run --rm -ti ubuntu:20.04@sha256:db6697a61d5679b7ca69dbde3dad6be0d17064d5b6b0e9f7be8d456ebb337209 /bin/bash

docker ps

Nous pouvons maintenant voir que la sortie docker ps affiche la balise qui a été spécifiée par la commande docker run.

372
12 - Sécurité
Ce qui précède peut sembler contre-intuitif. Les sommes de contrôle sha256 sont souvent utilisées pour vérifier une charge utile, par exemple lors de

l'utilisation de gestionnaires de packages pour installer ou mettre à niveau des applications.

Cette implémentation se comporte plus comme git. Dans git, chaque commit a un hachage - une somme de contrôle du contenu du commit - qui peut

être utilisé pour identifier de manière unique un ensemble de modifications dans un référentiel. Contrairement à git, cependant, qui permet de forcer

brutalement une mise à jour d'un commit qui briserait la somme de contrôle (c'est-à-dire de nouvelles modifications sur un commit existant), le

condensé Docker est utilisé à la fois comme identifiant (possibilité de rechercher) et comme vérification (assurer que l'image pointe vers ce qui est

prévu).

Les balises Docker se comportent également un peu comme les balises git. Une balise peut pointer vers un et un seul condensé, mais bien que les

condensés soient immuables, les balises peuvent être mises à jour pour déplacer le pointeur vers un nouveau condensé. Cela signifie que la

commande docker run ubuntu:20.04 peut donner un résultat différent entre les run. Cela peut présenter des risques en termes de sécurité et d'impact

opérationnel car cela permet des changements sans visibilité évidente.


373
12 - Sécurité
La solution pour empêcher le changement consiste à épingler un digest dans le conteneur en cours d'exécution - fait en

ajoutant @sha256:<digest>. Cela résout le problème de permettre à un conteneur de changer de manière inattendue.

Cela dit, au vu des exemples ci-dessus, on peut voir que lorsqu'un digest est spécifié au démarrage du conteneur, la balise

n'est plus respectée en aucune façon. Le registre Docker suit simplement les pointeurs vers lesquels digest une référence de

balise à l'heure actuelle, donc afin de maintenir la compatibilité descendante pour les images précédemment démarrées, il ne

vérifie pas la balise par rapport au registre au démarrage.

374
12 - Sécurité
Considérez ce scénario :

Vous exécutez un conteneur de production et vous souhaitez épingler une version de distribution particulière (restons sur Ubuntu ici), donc

vous épinglez la balise d'image sur ubuntu:20.04@sha256:8bce67040cd0ae39e0beb55bcb976a824d9966d2ac8d2e4bf6119b45505cee64 . Une

semaine plus tard, cette image peut recevoir des correctifs de sécurité et la balise sera mise à jour avec un nouveau condensé au fur et à

mesure que son contenu a changé. Si l'environnement d'exécution Docker vérifiait le registre au démarrage pour s'assurer que la balise

spécifiée correspondait correctement au condensé spécifié, les choses se compliqueraient rapidement. Pour que les choses restent

fonctionnelles, lorsque ce scénario est rencontré, Docker donne la priorité au condensé spécifié et l'exécute indépendamment du fait que

la balise existe ou ait jamais existé ou qu'elle pointe vers le condensé référencé.

375
12 - Sécurité
Le comportement affiche également par défaut la balise en cours d'exécution (c'est-à-dire en docker pssortie) en tant que balise spécifiée au moment

de la création du conteneur et ne mappe pas automatiquement un résumé en cours d'exécution vers une balise d'image locale mappée à l'image.

Cela serait également assez compliqué car plusieurs balises peuvent pointer vers le même résumé et les balises peuvent pointer vers différents

résumés au fil du temps.

- Lors de l'exécution de conteneurs Docker, il est conseillé de spécifier le digest. La spécification d'un digest a préséance sur la balise, et à moins

qu'elle ne soit vérifiée à une autre étape, la balise peut ne pas et ne jamais avoir été corrélée avec l'image de base d'un conteneur en cours

d'exécution

376
12 - Sécurité
Capabilities / Seccomp

Secure Computing Mode , également connu sous le nom de Seccomp, est une fonctionnalité du
noyau Linux qui améliore plusieurs fonctionnalités de sécurité pour aider à exécuter Docker dans un
environnement plus sécurisé.

Cela ressemble plus à un environnement de bac à sable qui agit non seulement comme un pare - feu
pour les appels système, mais vous permet également de restreindre les actions disponibles dans les
conteneurs Docker au noyau Linux de l'hôte.

Nous allons utiliser le site play with docker pour découvrir cette fonctionnalité

https://training.play-with-docker.com/security-seccomp/

377
12 - Sécurité
Scan de vulnérabilités
Il existe une fonctionnalité payante pour docker scan
docker scan --version
cela chez Docker : docker scan hello-world:latest
https://docs.docker.com/docker-hub/vulnerability-sca docker scan hello-world:latest --file Dockerfile
nning/ docker scan php:latest --dependency-tree
docker scan php:latest --severity low|medium|high
Vous pouvez toutefois utiliser la commande docker
docker scan --login
scan
Vous pouvez effectuer 10 scans gratuitement
chaque mois. Si vous vous connectez avec Snyk,
cela passe à 200 scans par mois.

378
12 - Sécurité
Comment communiquer en TLS avec le daemon docker ?
Ce qu'il faut faire pour la machine Ubuntu est de définir le fichier daemon.json sur le chemin
/etc/docker avec le contenu suivant :

{ "tls": true, "tlscert": "/var/docker/server.pem",


"tlskey": "/var/docker/serverkey.pem",
"hosts": ["tcp://x.x.x.y:2376",
"unix:///var/run/docker.sock"] }

379
12 - Sécurité
La sécurité dans un Swarm
Deux fonctionnalités de sécurité clés sont disponibles dans Docker Swarm. Tout d'abord, Docker est livré avec un
système d'infrastructure à clé publique (PKI) en mode swarm qui permet aux administrateurs de déployer en toute
sécurité un système d'orchestration de conteneurs.

Docker se désigne comme nœud de gestionnaire chaque fois qu'un administrateur crée un essaim en exécutant «
docker swarm init ». C'est alors que le nœud du gestionnaire génère une nouvelle autorité de certification racine (CA)
ainsi qu'une paire de clés pour chiffrer les communications avec les autres nœuds qui rejoignent l'essaim à l'aide de
Transport Layer Security. Les administrateurs ont la possibilité de spécifier une autorité de certification racine générée
en externe ainsi que de faire pivoter l'autorité de certification racine de l'essaim au cas où une clé de cluster CA ou un
nœud de gestionnaire serait compromis.

380
12 - Sécurité
Deuxièmement, Docker Swarm crypte les journaux Raft utilisés par les gestionnaires sur le
disque afin de protéger les informations de configuration et les données des attaquants. La
clé TLS utilisée pour crypter les communications du nœud de l'essaim ainsi que la clé des
journaux Raft sont chargées dans la mémoire de chaque nœud de gestionnaire. Les
administrateurs peuvent choisir de protéger ces clés en activant le verrouillage automatique,
une fonctionnalité qui nécessite que les gestionnaires soient déverrouillés manuellement
avec une clé de chiffrement de clé générée par Docker. Cette fonctionnalité permet ainsi
d'éviter que ces clés de chiffrement ne tombent entre de mauvaises mains.

381
13 - Monitoring
Gestion des logs
Les journaux Docker vous aident à accéder à la racine cause de tels problèmes et les résoudre
rapidement. Cependant, la gestion des journaux Docker n'est pas simple, car l'architecture Docker
est intrinsèquement différente de la traditionnelle systèmes ou serveurs.
Lorsque vous utilisez Docker, vos journaux d'application sont stocké dans des conteneurs
éphémères, qui ne prennent pas en charge le stockage persistant de journaux. Cela signifie que si
vous ne parvenez pas à collecter ou à surveiller ces journaux en raison du réseau latence ou tout
autre problème, vous risquez de perdre ces journaux. Il n'y a pas moyen pour récupérer ces
journaux si un conteneur s'arrête.

382
13 - Monitoring
Gestion des logs

Un autre défi majeur avec la journalisation Docker est les outils et pratiques traditionnels de
gestion et d'analyse des journaux qui ne sont pas adaptés pour la journalisation Docker. Même la
configuration Docker la plus basique peut nécessiter la collecte de logs provenant de plusieurs
sources, y compris les logs de différents conteneurs et serveurs hôtes.

De plus, il existe plusieurs façons de collecter les journaux Docker. Vous pouvez choisir un volume
de données pour la gestion centralisée des journaux ou configurez la journalisation Docker pilote,
ou configurez un conteneur de journalisation dédié pour gérer vos journaux Docker. Comprendre
les avantages de toutes ces méthodes et choisir la bonne la configuration de la gestion des
journaux Docker peut prendre beaucoup de temps et effort.

383
13 - Monitoring
Les conteneurs Docker émettent des journaux vers les flux de sortie stdout et stderr. Étant donné que les
conteneurs sont sans état, les journaux sont stockés sur l'hôte Docker dans des fichiers JSON par défaut.

Pourquoi? Le pilote de journalisation par défaut est json-file. Les journaux sont ensuite annotés avec l'origine du
journal, stdout ou stderr, et un horodatage. Chaque fichier journal contient des informations sur un seul
conteneur. Vous pouvez trouver ces fichiers journaux JSON dans le répertoire /var/lib/docker/containers/ sur
un hôte Docker Linux. Voici comment vous pouvez y accéder :

/var/lib/docker/containers/<container id>/<container id>-json.log

384
13 - Monitoring
C'est là que la journalisation entre en jeu. Vous pouvez collecter les journaux avec un agrégateur de journaux et les stocker dans un
endroit où ils seront disponibles pour toujours. Il est dangereux de conserver des journaux sur l'hôte Docker, car ils peuvent
s'accumuler au fil du temps et consommer de l'espace disque.

C'est pourquoi vous devez utiliser un emplacement central pour vos journaux et activer la rotation des journaux pour vos conteneurs
Docker.

Les conteneurs sont à plusieurs niveaux

C'est l'un des plus grands défis de la journalisation Docker. Quelle que soit la base de votre installation Docker, vous devrez travailler
avec deux niveaux d'agrégation. L'un fait référence aux journaux de l'application Dockerized à l'intérieur du conteneur. L'autre
implique les journaux des serveurs hôtes, qui se composent des journaux système, ainsi que les journaux Docker Daemon qui sont
généralement situés dans /var/log ou un sous-répertoire de ce répertoire.

Un simple agrégateur de journaux qui a accès à l'hôte ne peut pas simplement extraire les fichiers journaux de l'application comme
s'il s'agissait de fichiers journaux de l'hôte. Au lieu de cela, il doit pouvoir accéder au système de fichiers à l'intérieur du conteneur
pour collecter les journaux. De plus, votre infrastructure s'étendra inévitablement à davantage de conteneurs et vous devrez trouver
un moyen de corréler les événements de journal aux processus plutôt qu'à leurs conteneurs respectifs.

385
13 - Monitoring
Gestion des logs

Nous allons aborder certaines de ces principales méthodes pour gestion des
journaux Docker :

1 - Pilote de logs Docker

2 - Volume de données

3 - Conteneur de logs dédié

386
13 - Monitoring
Pilote de journalisation Docker

Le pilote de journalisation Docker fournit un moyen simple pour collecter les journaux Docker. Chaque fois que
vous créez un nouveau conteneur Docker, le Docker daemon utilise le pilote de journalisation par défaut pour lire
les événements de journal. Ces événements de journal sont stocké dans le Syslog de la machine hôte.

Il lit tout depuis le conteneur sortie stdout et stderr. Vous pouvez également modifier le pilote de journalisation
par défaut avec un autre plugin de pilote de journalisation de votre choix et transmettez vos journaux à un autre
emplacement ou un outil de gestion des journaux.

https://docs.docker.com/config/containers/logging/configure/

387
13 - Monitoring
Volumes de données

Nous avons discuté plus tôt de la façon dont les conteneurs Docker sont éphémères ou apatrides par nature.
Pour vous assurer que les journaux ne sont pas perdus lorsqu'un conteneur s'arrête, vous pouvez transférer ces
journaux à un service d'agrégation de journaux.

Une autre alternative consiste à stocker les événements de journal dans un volume de données, qui fournissent
un stockage à long terme. Les volumes de données mappent chaque répertoire d'un conteneur au répertoire
respectif d'une machine hôte. Le seul inconvénient de cette méthode est qu'elle restreint le mouvement des
conteneurs d'un hôte à l'autre.

388
13 - Monitoring
Conteneur de journalisation dédié

Le conteneur de journalisation dédié vous aide à gérer vos journaux d'application Docker dans l'environnement
Docker.

Vous pouvez collecter des logs à partir de différents conteneurs, les stocker dans un seul emplacement et
également les envoyer à un autre emplacement pour analyse ou archivage. Un avantage de cette méthode est
qu'elle vous permet de stocker des journaux sans dépendre de la machine hôte du conteneur.

389
13 - Monitoring
Logging à l'aide de l'approche side-car

Pour les déploiements plus importants et plus complexes, l'utilisation d'un side-car est l'une des approches les plus
populaires pour la journalisation des architectures de microservices.

De la même manière que la solution de conteneur dédié, elle utilise des conteneurs de journalisation. La différence est
que cette fois, chaque conteneur d'application a son propre conteneur dédié, vous permettant de personnaliser la solution
de journalisation de chaque application. Le premier conteneur enregistre les fichiers journaux sur un volume qui sont
ensuite étiquetés et expédiés par le conteneur de journalisation à une solution de gestion des journaux tierce.

L'un des principaux avantages de l'utilisation des side-cars est qu'il vous permet de configurer des balises personnalisées
supplémentaires pour chaque journal, ce qui vous permet d'identifier plus facilement leur origine.

Cependant, il existe certains inconvénients : il peut être complexe et difficile à configurer et à faire évoluer, et il peut
nécessiter plus de ressources que la méthode de journalisation dédiée. Vous devez vous assurer que le conteneur
d'application et le conteneur side-car fonctionnent comme une seule unité, sinon vous risquez de perdre des données.

390
13 - Monitoring
Nous allons aborder l’utilisation d’un logging driver puis nous verrons comment exploiter Prometheus et
Grafana avec nos containers

Qu'est-ce qu'un pilote de journalisation (logging driver) ?

Les pilotes de journalisation sont les mécanismes de Docker pour collecter des données à partir de conteneurs
et de services en cours d'exécution afin de les rendre disponibles pour l'analyse. Chaque fois qu'un nouveau
conteneur est créé, Docker fournit automatiquement le pilote de journal de fichier json si aucune autre option de
pilote de journal n'a été spécifiée. En même temps, il vous permet d'implémenter et d'utiliser des plugins de
pilote de journalisation si vous souhaitez intégrer d'autres outils de journalisation.

Voici un exemple d'exécution d'un conteneur avec un pilote de journalisation personnalisé, dans ce cas syslog :

docker run --log-driver syslog --log-opt syslog-address=udp://syslog-server:514 \


alpine echo hello world

391
13 - Monitoring
Comment configurer le pilote de journalisation Docker ?

Lorsqu'il s'agit de configurer le pilote de journalisation, vous avez deux options :

1. configurer un pilote de journalisation par défaut pour tous les conteneurs


2. spécifier un pilote de journalisation pour chaque conteneur

Dans le premier cas, le pilote de journalisation par défaut est un fichier JSON, mais, comme mentionné
ci-dessus, vous disposez de nombreuses autres options telles que logagent, syslog, fluentd, journald, splunk,
etc. Vous pouvez passer à un autre pilote de journalisation en modifiant le Docker de configuration et en
modifiant le paramètre log-driver, ou en utilisant votre expéditeur de journal préféré.

392
13 - Monitoring

# /etc/docker/daemon.json
{
"log-driver": "journald"
}

systemctl restart docker

Vous pouvez également choisir de configurer un pilote de journalisation conteneur par conteneur.
Comme Docker fournit un pilote de journalisation par défaut lorsque vous démarrez un nouveau
conteneur, vous devez spécifier le nouveau pilote dès le début en utilisant les paramètres -log-driver et
-log-opt.

393
13 - Monitoring

docker run --log-driver syslog --log-opt syslog-address=udp://syslog-server:514 \


alpine echo hello world

Où les journaux Docker sont-ils stockés par défaut ?


Le pilote de journalisation vous permet de choisir comment et où envoyer vos données. Le pilote de
journalisation par défaut est un fichier JSON situé sur le disque local de votre hôte Docker :

/var/lib/docker/containers/[container-id]/[container-id]-json.log

394
13 - Monitoring
Gardez à l'esprit, cependant, que lorsque vous utilisez un autre pilote de journalisation que json-file ou
journald, vous ne trouverez aucun fichier journal sur votre disque. Docker enverra les journaux sur le
réseau sans stocker de copies locales. C'est risqué si jamais vous devez faire face à des problèmes de
réseau.

Dans certains cas, Docker peut même arrêter votre conteneur, lorsque le pilote de journalisation ne
parvient pas à envoyer les journaux. Ce problème peut se produire selon le mode de livraison que vous
utilisez.

395
13 - Monitoring
Comment travailler avec les journaux de conteneur Docker à l'aide de la commande docker logs ?

Docker a une commande dédiée qui répertorie les journaux de conteneurs. La commande docker logs.
Le flux implique généralement que vous vérifiiez vos conteneurs en cours d'exécution avec docker ps,
puis vérifiez les journaux en utilisant l'ID d'un conteneur.

docker logs <container_id>

Cette commande répertorie tous les journaux du conteneur spécifié. Vous pouvez ajouter un indicateur
d'horodatage et répertorier les journaux pour des dates particulières.

docker logs <container_id> --timestamps


docker logs <container_id> --since (or --until) YYYY-MM-DD
396
13 - Monitoring
Ce que vous finirez par faire sera de suivre ces journaux, soit pour vérifier le dernier nombre N de
lignes, soit pour suivre les journaux en temps réel.

L'indicateur --tail affichera les N dernières lignes de journaux :

docker logs <container_id> --tail N

Vous pouvez bien sûr utiliser grep pour certains patterns recherchés :

docker logs <container_id> | grep pattern


docker logs <container_id> | grep -i error

397
13 - Monitoring
Ce que vous finirez par faire sera de suivre ces journaux, soit pour vérifier le dernier nombre N de
lignes, soit pour suivre les journaux en temps réel.

L'indicateur --tail affichera les N dernières lignes de journaux :

docker logs <container_id> --tail N

Vous pouvez bien sûr utiliser grep pour certains patterns recherchés :

docker logs <container_id> | grep pattern


docker logs <container_id> | grep -i error

398
13 - Monitoring

Une fois qu'une application commence à se développer, vous avez tendance à commencer à
utiliser Docker Compose. Il y a également une commande de journaux.

docker-compose logs

Cela affichera les journaux de tous les services de l'application définie dans le fichier de
configuration Docker Compose.

399
13 - Monitoring

Nous avons un exemple d’utilisation avec Prometheus. Le but de prometheus


était de scraper des données en version timeseries

https://docs.docker.com/config/daemon/prometheus/

400
13 - Monitoring

ELK

401
13 -Exploiter les logs avec ELK

Nous allons lier deux machines virtuelles : une contenant docker et une contenant
la stack ELK

Aller sur la machine dockerelk : vagrant ssh dockerelk

sudo -s
vim install_elk.sh

402
13 -Exploiter les logs avec ELK
input {
Nous allons utiliser un type de logs dit gelf gelf {
type => docker
port => 12201
https://docs.docker.com/config/containers/logging/gelf/
}
}
Il faudra donc configurer le logstash pour qu’il récupère
le format graylog et docker pour qu’il envoie du format output {
graylog elasticsearch {
hosts => ["127.0.0.1:9200"]
⇒ Edition du logstash sur index =>
/etc/logstash/conf.d/docker.conf "logstash-dk-%{+YYYY.MM.dd}"
}
}

403
13 -Exploiter les logs avec ELK

Ensuite nous ferons un test oneshot sur le conteneur unique :

docker run --log-driver gelf --log-opt gelf-address=udp://192.168.20.101:12201 alpine


echo hello world

404
13 -Exploiter les logs avec ELK
{
"log-driver": "gelf",
Sinon édition du /etc/docker/daemon.json "log-opts": {
"gelf-address": "udp://192.168.20.101:12201"
}
}

systemctl daemon-reload
systemctl restart docker

Le test s’effectuera alors avec tous les containers lancés : docker run -p 80:80 nginx

405
13 -Exploiter les logs avec ELK
Sur dockerelk : systemctl status elasticsearch

Chercher l’ip (souvent en eth1) :

Puis aller sur cette ip avec le port d’elasticsearch 9200

systemctl status kibana

Puis aller sur cette même ip avec le port d’elasticsearch 5601

406
13 -Exploiter les logs avec ELK
systemctl status logstash

Il nous reste maintenant à créer notre configuration docker.conf

vim /etc/logstash/conf.d/docker.conf

L’index nous permettra ensuite de travailler avec kibana systemctl restart logstash

vagrant ssh formdock

Vérifier que docker est bien installé avec docker ps par exemple

407
13 -Exploiter les logs avec ELK

Nous allons ensuite injecter des données pour logstash en utilisant la commande oneshot
(attention à l’ip de la machine)

docker run --log-driver gelf --log-opt gelf-address=udp://192.168.20.101:12201 alpine


echo hello world

Cette commande sera lancée dans formdock. Pour voir les logs dans kibana, aller dans les
réglages en bas → index management → sélectionner l’index envoyé → Aller dans la boussole en
haut à gauche → create index pattern → logstash-dk* → next step → @timestamp → create
index pattern → recliquer sur la boussole.

408
13 -Exploiter les logs avec ELK

Si maintenant on veut le faire pour l’ensemble des containers

sur formdock ⇒ éditer le /etc/docker/daemon.json

{
"log-driver": "gelf",
"log-opts": {
"gelf-address": "udp://192.168.20.101:12201"
}
}

systemctl daemon-reload

409
13 -Exploiter les logs avec ELK

systemctl restart docker

docker run --name webserver -p 80:80 nginx

curl 127.0.0.1 plusieurs fois

Puis vérifier les logs sur Kibana

410
14 - Docker Entreprise
Présentation

Docker Enterprise Edition (Docker EE) est conçu pour les équipes de développement d'entreprise et
informatiques qui créent, livrent et exécutent des applications stratégiques en production et à grande
échelle. Docker EE est intégré, certifié et pris en charge pour fournir aux entreprises la plate-forme de
conteneurs la plus sécurisée du secteur.

Il existe actuellement deux versions de Docker EE Engine disponibles :

18.03 - Utilisez cette version si vous n'exécutez que Docker EE Engine.


17.06 - Utilisez cette version si vous utilisez Docker Enterprise Edition 2.0 (Docker Engine, UCP et DTR).
Cependant … : https://forums.docker.com/t/how-to-download-docker-enterprise/112312
En revanche en utilisation pro , cliquez sur upgrade sur le Docker Desktop par exemple…

411
15 - Projets avec l’écosystème Docker
Tutos et cours intéressants :
https://medium.com/devops-with-valentine/how-to-deploy-a-docker-container-to-a
ws-elastic-beanstalk-using-aws-cli-87ccef0d5189
Alternatives à Docker :
https://rigorousthemes.com/blog/best-docker-alternatives/
Docker déprécié sur Kubernetes ???
https://dev.to/inductor/wait-docker-is-deprecated-in-kubernetes-now-what-do-i-do-e4m

https://www.freecodecamp.org/news/7-cases-when-not-to-use-docker/

412
15 - Projets avec l’écosystème Docker

Pourquoi Docker serait déprécié sur Kubernetes ?


Docker ne prend pas en charge Kubernetes Runtime API appelée CRI (Container Runtime Interface)
et que les gens de Kubernetes utilisent un service de pont appelé « dockershim ». Il convertit l'API
Docker et le CRI, mais il ne sera plus fourni du côté de Kubernetes dans quelques versions
mineures. Docker en local est un outil très puissant pour créer un environnement de développement
à coup sûr, mais pour comprendre ce qui en est la cause, vous devez comprendre ce que Docker
fait dans l'architecture Kubernetes actuelle. Kubernetes est un outil d'orchestration infra qui regroupe
de nombreuses ressources de calcul différentes telles que des machines virtuelles / physiques et le
fait ressembler à une énorme ressource de calcul à exécuter et à partager avec d'autres. Dans cette
architecture, Docker, ou un runtime de conteneur, est utilisé uniquement pour exécuter ces
applications dans un hôte réel en étant planifié par le plan de contrôle Kubernetes.
https://kubernetes.io/blog/2020/12/02/dont-panic-kubernetes-and-docker/

413

Vous aimerez peut-être aussi