Docker
Docker
-1-
:)
::1
Il
1:--
l:J
0
c
::J
© Dunod, 20 16
0 11 rue Paul Bert, 92240 Malakoff
\.0
.-t [Link]
0
N
@ lSBN 978-2-10-075350-5
.......
..c:
O'l
·;::
>-
0.. Le Code de Io propriété intellectuelle n'oulorisont, aux termes de l'article
0
u L. 122-5, 2° et 3° a), d'une part, que les «copies ou reproductions strictement
réservées o l'usage privé du copiste et non destinées o une utilisation collective »
et, d'autre part, que les analyses et les courtes citations dons un but d'exemple el
d' illustration, cc toute représentation ou reproduction intégrale ou partielle faite
sons le consentement de l'a uteur ou de ses ayants droit ou ayants couse est
illicite ,. (art. L. 122-4).
Cette représentation ou reproduction, por quelque procédé que ce soit, constitue-
rait donc une contrefaçon sanctionnée por les articles L. 335-2 et suivants du
Code de Io propriété intellectuelle.
Table des matières
Avant,propos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . XI
@
'ii
·c 1.2 .3 N amespaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ÎÎ
....... B
..c
:::;
CO 1.2.4 Qu'est,ce qu'un conteneur finalement?................................. ÎÎ
O'l c
0
ï::::: c
>-
o. c 1.3 Les apports de Docker : structure en couches, images, volumes et registry .... IT
u
0 ·3ù
:::;
"O
0
1.3 .1 La notion d'image ................................................... . IT
....
c.
~ 1.3.2 Organisation en couches : union file system ............................. . IT
~
:::;
rS 1.3 .3 Docker Hub et registry ....................... ........................ . T4
17
1
"O
0
1.3.4 Copy on write, persistance et volumes . ....................... .. ........ .
c
8
(Ç)
S Docker
"'Cl
0
c Deuxième partie - Docker en pratique : les outils de base
:::i
0
\.0
C: Chapitre 3 - Prise en main . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
N
@ 3 .1 Installation de Docker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
.......
-§i 3 . l. l Docker Toolbox : la solution rapide pour Windows et Mac OS X. . . . . . . . . . . . 55
ï:::::
~ 3 .1 . 2 Linux sous VirtualBox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
u
3.2 Votre premier conteneur.... . .......... ...... ............ .......... ..... 64
3 .2. 1 Kitematic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
3 .2. 2 Le client Docker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
3 .2. 3 API Docker Remote . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
Table des matières 0
Chapitre 4 - Docker sur un serveur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
4 .1 Docker Machine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
4. 1 . 1 Installation de Docker Machine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
4 .1 . 2 Prise en main de Docker Machine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
4 .1 .3 La commande docker-machine create . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
4 .1 .4 Installation de Docker avec Docker Machine sur Amazon AWS . . . . . . . . . . . . . 77
4 .1 .5 Installation de Docker avec Docker Machine et Oracle VirtualBox . . . . . . . . . . . 81
4.1 .6 Quelques autres commandes utiles...................................... 82
"'Cl
0
c
:::i
0
\.0
.-t
0
N
@
.......
..c
O'l
'i:
>-
0.
0
u
Avant-propos
L'apport de la virtualisation
La virtualisation a tenté de répondre à cette problématique (parmi d'autres) sans
apporter une réponse complètement satisfaisante. En effet, bien qu'offrant une
isolation vis-à-vis de l'arc hitecture matérielle, qui se standardise de plus en plus, la
machine virtuelle reste ... une machine. Elle exécute un système d'explo itation dont
les paramètres peuvent différer d 'un environnement à l'autre.
Des outils comme Chef ou Puppet résolvent une partie du problème, mais
n'offrent encore une fois qu'une couche d'abstraction partielle. Enfin, le déploiement
d'application sur la base d'une image de VM (pour Virtual Machine) est lourd (plusieurs
l:J gigaoctets, y compris pour les OS les plus compacts).
0
c
::J
~
,.,
"O
0 c::;
\.0 Les architectures à base de conteneurs
.-t
0
.,.,
~
N
'~ Avec Docker, n ous sommes entrés dans l'ère des architectures à base de « conteneur» .
@ ·c
....... B::;
On parle aussi de « v irtualisation de niveau système d'exploitation » par opposi-
..c: CO
Ol
0
c tion aux technologies à base d'hyperviseurs (comme VMWare ou VirtualBox) qui
ï:::: c
>-
o.. c cherchent à émuler un environnement matériel.
u
0 ·3
<.)
::;
"O
C ontrairement à une VM, un conteneur n'embarque pas un système d'explo itation
0
.....
c. complet. Il repose pour l'essentiel sur les fonctionnalités offertes par l'OS sur lequel
~
~ il s'exécute. L'incon vénient de cette approche est qu'elle limite la portabilité du
::;
rS conteneur à des OS de la même famille (Linux dans le cas de Docker). Cette approche,
1
"O
0
en revanch e, a l'avantage d'être beaucoup plus légère (les conteneurs sont nettement
c
8 plus petits que les VM et plus rapides au démarrage ) tout en offrant une isolation
(Ç) satisfaisante en termes de réseau, de mémoire ou de système de fichiers.
Étonnamment, le concept de conteneur et son implémentation ne sont pas
nouveaux. La version de OpenVZ pour Linux date, par exemple, de 2005, de même
que Solaris Zone ou FreeBSD jail. Docker a changé la donne en simplifiant l'accès à
cette technologie par l'introduction d'innovations, comme la mise à disposition d'un
langage de domaine (DSL ou Domain Specific Language) permettant, au travers des
fameux « Dockerfile »,de décrire très simplement la configuration et la construction
d'un conteneur.
La structure du livre
l:J
0 Dans une première partie, nous expliquerons ce qu'est un conteneur, sur quels principes
c
:J et quelles technologies il repose. Nous verrons aussi comment Docker se positionne
0
\.0 parmi un nombre croissant d'acteurs et de logiciels importants.
.-t
0
N Nous aborderons ensuite le concept de « CaaS »,pour« Container as a Service »,au
@ travers de divers exemples. À cette occasion, nous utiliserons des outils tels que Swarm,
.......
..c: Kubernetes, Mesos. Nous nous intéresseron s aux liens entre les approches conteneurs
O'l
·;::
>- et celles d'outils de gestion de configuration comme Puppet, Chef ou Ansible.
0..
0
u La seconde partie de cet ouvrage se focalise sur la prise en main de Docker en
étudiant son installation sur un poste de travail ou dans un environnement serveur
virtualisé ou physique. Nous commencerons alors à « jouer» avec des conteneurs pour
comprendre par la pratique les concepts abordés dans la première partie.
La troisième partie du livre est consacrée à l'apprentissage de Docker. Nous y
aborderons les commandes du client et les instructions du Dockerfile. Cette troisième
partie peut être lue séquentiellement, mais aussi servir de référence.
Avant-propos ------------------------------!XII '
La dernière partie du livre se compose de trois chapitres qui mettent en œuvres des
cas d'usages permettant d'aborder des concepts plus avancés comme:
• les architectures multi~processus et multi~conteneurs ;
• la réalisation d'une chaîne d'intégration continue s'appuyant sur l'usage de
conteneurs ;
• la mise en œuvre d'un cluster multi~hôtes en s'appuyant sur Docker Swarm.
• si vous êtes engagé dans une organisation de développement (en tant que
développeur, architecte ou manager), vous trouverez les informations nécessaires
pour maîtriser rapidement la conception d'images Docker, mais aussi pour la
réalisation d'architectures multi~conteneurs;
• si votre domaine est plutôt celui de l'explo itation, vous acquerrez les compé~
tences nécessaires au déploiement de Docker sous Linux.
Compléments en ligne
Le code source et les exemples de ce livre sont distribués via GitHub sur le repository
public:
[Link]
Un erratum, des articles et des exemples complémentaires sont aussi distribués via le
"'Cl
0 site [Link]
c
:::i
~
,.,
"O
0 [Link];
\.0
.-t ~
0
N
V
V Remerciements
'ii
@ ·c
....... [Link]; L'écriture d'un livre est une activité consommatrice de temps qu'il n'est pas possible
..c CO
O'l c
0 de mener à son terme sans l'assistance de nombreuses personnes.
ï::::: c
>-
o. c
0 ·3ù Nous voudrions donc adresser nos remerciements à :
u :::;
"O
0
.... • Patrick Moiroux, pour son expertise de Linux en général, des architectures web
c.
~ distribuées et de Docker en particulier ;
~
:::;
rS • Bernard Wittwer, pour avoir attiré notre attention, il y a plus de trois ans, sur
"O
1
un petit projet OpenSource sympathique nommé Docker dont il percevait déjà
0
c le potentiel ;
8
(Ç) • Marc Schar, notre stagiaire de compétition, devenu expert de Kubernetes ;
• tous les contributeurs au projet open source BizDock ([Link]
[Link]/) qui a été notre premier contact avec le monde des conteneurs
et Docker;
• nos épouses et nos enfants pour leur patience en regard du temps que nous avons
passé isolés du monde extérieur à expérimenter des logiciels et à en décrire le
fonctionnement.
"'Cl
0
c
:::i
0
\.0
.-t
0
N
@
.......
..c
O'l
'i:
>-
0.
0
u
...
PREMIERE PARTIE
Les conteneurs ••
principes, obiectifs et
solutions
métal standardisées qui transportent de nos jours l'essentiel des biens matériels par
camion, train, avion ou bateau.
Nous allons donc faire un peu d'histoire.
Avant l'apparition de ces conteneurs standardisés, les biens étaient manipulés manuel,
lement. Les A nglo,Saxons utilisent le terme de break bulk cargo, ce que nous pourrions
traduire par « chargement en petits lots » . Plus simplement, les biens étaient chargés
individuellement par des armées de travailleurs.
Les biens étaient, par exemple, produits dans une usine, chargés un par un dans
un premier moyen de transport jusqu'à un han gar (généralement près d'un port ou
d'une gare ) où avait lieu un déchargement manuel. Un second ch argement survenait
alors depuis ce premier lieu de stockage jusque dans le moyen de transport lon gue
distance (par exemple un bateau). C e second ch argement était lui aussi manuel. En
fonction des destinations, des contraintes géographiques et légales, cette séquence de
chargement et déchargement pouvait avoir lieu plusieurs fo is. Le transport de biens
était donc coûteux, lent et peu fiable (biens abîmés ou perdus).
Les premières tentatives de standardisation du transport de biens sont intervenues
en A n gleterre à la fin du XVIIe siècle, essentiellement pour le transport du charbon.
L'un des exemples bien connus est celui de la ligne de ch emin de fer Liverpool -
Manchester qui utilisait des boîtes en bo is de taille standardisée qui étaient ensuite
d éch argées p ar grues sur d es ch arre ttes tirées p ar des chevaux .
Dans les années trente, la C hambre inte rnationale de commerce a mené des
tests afin de standardiser les conteneurs en vue de faire baisser les coûts de transport
dans le contexte de la grande dépression de 1929. En 1933, le Bureau international
des conten eurs ou BIC est établi à Paris (et il s'y trouve toujours) pour gérer la
standardisation de ces grosses boîtes métalliques dont le succès n 'a fait que croître
l:J
depuis.
0
c
::J
0
\.0
.-t
0
N
@
.......
1111111 1111 . ~ j i~
..c: ' .
O'l
·;:: . '·; I
~ ~
>-
0..
0
u
Les avantages du transport par conteneur intermodal sont liés à ce que les Anglo-
Saxons n omment separation of concems (en français ségrégation des problèmes ou
ségrégatio n des responsabilités).
Les transporteurs délèguent à leurs clients le remp lissage du conteneur qui est
ensuite scellé avant le transport. De ce fait, le transporteur n'a pas à s'occuper de
la na ture précise des biens tran sportés. Il do it s'assurer que le conten eur d ans son
ensemble arrive intact. Il assure donc la traçabilité d'un obj et dont les caractéristiques
physiques sont standardisées. Il peut les empiler, cho isir le mode de transport adapté à
la destinatio n, optimiser les coûts et la logistique. Camions, bateaux, trains et grues
vont pouvoir traiter ces biens, les arrimer correctement, qu'ils transportent des armes
ou des couches-culottes.
La personne ou l'entreprise cliente a de son côté la garantie, pour peu que le
contene ur ne soit pas perdu ou ouvert, que ses biens arriveront dans le même état
et arran gement que lors du chargement. Le client n'a donc pas à se soucier de
l'infrastructure de transport.
C ette séparation des responsabilités est à l'origine de la baisse drastique des coûts
du transport de marchandises. Grâce à la standardisation et à l'automatisation qu'elle
rend possible, les infrastructures de transport se sont mécanisées, automatisées et donc
fiabilisées.
u
o..
0
c
·3
<.)
::;
"O
0
.....
c.
• conteneur 1 conteneur l_c_
on_t_e_n_e_u_r_.
~
~
::;
rS
1
"O
0
développeur
c
8 Figure 1.2 - Séparation des responsabilités dans une architecture à conteneurs
(Ç)
ŒJ------------------- Chapitre 1. Les conteneurs et le cas Docker
Étudion s l'empilement des couches dans le cas du déplo iement de trois logiciels sur
un mê me hôte (host) sans machine v irtuelle ou conteneur.
BBB os
Infrastructure
l:J
• les différents logiciels peuvent interagir entre eux s'ils n 'ont pas été conçus
0
c par le même éditeur. Ils pourraient, par exemple, nécessiter des packages
::J
0 (bibliothèques, extensions) ou des versions de système d'exploitation différen tes.
\.0
.-t Ils peuvent aussi ouvrir des ports réseaux identiques, accéder aux mêmes chemins
0
N sur le système de fichiers ou encore entrer en concurrence pour les ressources
@
.......
1/0 ouCPU ;
..c:
Ol
·;::
• toute mise à jour de l'O S hôte va nécessairement impacter tous les logiciels qui
>-
0..
tournent dessus ;
0
u • chaque mise à jour d'un logiciel pourrait entraîner des impacts sur les autres.
1OS hôte
Infrastructure
Dans les faits, comme nous le voyons sur la figure précédente, cette virtualisation
matérielle offre un niveau d'isolation élevé. Chaque logiciel se trouve dans son bac à
sable (sandbox en anglais). Les problèmes évoqués précédemment sont donc résolus,
mais d'autres apparaissent :
• le poids d'une machine virtuelle est tout d'abord très important. Une machine
virtuelle est une machine et , même avec un système d'exploitation minimal,
un OS moderne consommera difficilement moins de quelques Go de mémoire.
La distribution de ce type de package demandera une bande passante réseau
conséquente;
• la machine virtuelle embarque trop d'éléments. Elle ne laisse pas le choix à
l:J
0 l'exploitant (selon la manière dont elle aura été configurée) de choisir librement
c ~
,.,
::J
"O
ses caractéristiques, comme le type de stockage, le nombre de CPU utilisés, la
0 c::;
\.0 configuration réseau. Évidemment, les solutions de gestion d'environnements
.-t
0
.,.,
~
virtualisés (par exemple, vCenter de VMWare) offrent des solutions, mais celles~
N
'~
@ ·c ci ont presque toujours des impacts sur le logiciel. Ce dernier ne peut pas être
....... B
..c:
::;
CO conçu sans savoir comment il va être exécuté .
Ol c
ï:::: 0
>- c
o.. c Une architecture à base de conteneurs offre une solution de compromis. Le
u
0 ·3
<.)
::; conteneur offre l'isolation permettant à un développeur d'embarquer l'ensemble des
"O
0
.....
c. dépendances logicielles dont il a besoin (y compris les dépendances de niveau OS).
~
~
De plus, un conteneur s'appuie sur le noyau (kemel) du système d'explo itation hôte 1.
::;
rS
1
"O
0 l. Sur la figure 1.5, le lecteur attentif aura noté les termes « cgroups » et « namespaces ». Nous les
c
8 définirons dans le paragraphe suivant. À ce stade, nous dirons qu'il s'agit d'extensions du noyau
(Ç) Linux qui rendent possible la réalisation de conte neurs « isolés » les uns des autres.
ŒJ------------------- Chapitre 1. Les conteneurs et le cas Docker
Infrastructure
Il est donc très léger et démarre presque aussi vite que le processus qu'il encapsule. Le
nombre de conteneurs qu'un même hôte peut exécuter est donc nettement plus élevé
que son équivalent en machines v irtuelles.
l:J
0 Il existe par ailleurs des projets, comme Fedora Atomic ou CoreOS, visant à offrir
c
::J des OS hôtes minimaux dédiés à l'exécution de conteneurs et se focalisant uniquement
0
\.0 sur les problématiques d'infrastructure. L'usage de ces OS hôtes spécialisés va limiter
.-t
0 leur exposition aux attaques et aux bugs pouvant nécessiter des mises à jour.
N
@ Nous verrons aussi plus tard que Docker apporte deux autres avantages aux
.......
..c: solutions à base de conteneurs : la possibilité de décrire formellement comment
Ol
·;::
>- construire le conteneur et un format d'image standardisé. Cette capacité fondamen tale
0..
0 est probablement la clef du succès de Docker.
u
Maintenant que nous sommes convaincus des avantages des architectures à base
de conten eurs, nous allons en étudier les fondements techniques.
1.2 Les fondations: Linux, CGroups et N amespaces -----------------[!]
1.2 LES FONDATIONS: LINUX, CGROUPS
ET NAMESPACES
Docker est une solution open source de conteneurs Linux qui s'appuie elle-même sur
d'autres composants eux aussi ouverts. Ces briques de base sont en fait communes à
tous les types de conteneurs Linux.
Initialement, Docker utilisait notamment LXC (Linux Containers) comme implé-
mentation (on parle de driver), mais a depuis développé sa propre bibliothèque de
bas niveau nommée libcontainer 1 • Ce driver encapsule les fonctionnalités fondamen-
tales, proches du noyau du système d'exploitation, dont la combinaison permet la
virtualisation.
Nous allons étudier ces différents composants de base pour:
• en comprendre le rôle fonctionnel ;
• comprendre les différentes étapes qui ont abouti au concept de conteneur.
"'Cl
V irtualBox est un hyperviseur open source (disponible en licence GPU aujourd'hui
0
c ~
géré par O racle. Il est donc très fréquemment utilisé par des solutions open source
:::i ,.,
0 "O souhaitant disposer de fonctionnalités de virtualisation sans contraintes de licences.
[Link];
\.0
.-t ~
0
N
V
V Comme nous le verrons dans le chapitre suivant, l'installation de la Docker
'ii
@ ·c Toolbox (le kit de démarrage de Docker en environnement PC) sous Windows ou
....... [Link];
..c CO Mac OS X inclut VirtualBox et une image Linux minimale qui fournit les services
O'l c
ï::::: 0
c nécessaires à l'exécution du Docker Engine. L'installation n'est donc pas native et la
>-
o. c
0 ·3ù complexité de gestion des terminaux, comme les performances d'accès au système de
u :::;
fichiers, limite très fortement l'intérêt de Docker sous ces OS Desktop.
"O
0
....
c.
~
~
:::;
rS 1. Notons que ce driver d 'exécut ion est ce qui fait le pont entre le moteur d'exécution des
1
"O
0 conteneurs et le système d 'exploitation. Dans le cas de l'implémentation native sous W indows,
c
8 c'est ce composant que les équipes de Microsoft ont dû réécrire pour l'adapter à Windows.
(Ç) 2. h ttps://www.v [Link]/
El------------------- Chapitre 1. Les conteneurs et le cos Docker
1.2.2 CGroups
CGroups 1 (pour Control Groups) permet de partitionner les ressources d'un hôte
(processeur, mémoire, accès au réseau ou à d'autres terminaux). L'objectif est de
contrôler la consommation de ces ressources par processus.
Prenons par exemple une machine sur laquelle serait installée une application
web avec un front,end PHP et une base de données MySQL. CGroups permettrait
de répartir la puissance de calcul (CPU) et la mémoire disponible entre les différents
processus, afin de garantir une bonne répartition de la ch arge (et donc probablement
des temps de réponse).
l:J
0 RAM CP Us
c
:i
0
\.0
.-t
0
N
@
.......
..c
en
ï:::::
>-
0.
0
u web-front-end group database group
PI D CMD PID CMD
7459 httpd . worker 11751 mysqld-safe
7462 httpd .worker 11958 mysqld
1.2.3 Namespaces
Les Namespaces sont indépendants de CGroups, mais fon ctionnent de concert. Ils
permettent de faire en sorte que des processus ne voient pas les ressources utilisées par
d'autres. Si C G roups gère la distribution des ressources, N amespaces apporte l'isolation
nécessaire à la créatio n de conteneurs.
L'ancêtre du mécanisme des N amespaces est la commande chroot qui existe au
sein du système U N IX depuis 1979 !
La fonction de cette commande est de ch anger pour un processus donné le
répertoire racine du système. Le processus en question a l'impression d'être à la racine
du système. L'objectif étant, par exemple, pour des raisons de sécurité, d 'empêch er
l'utilisateur de se promener dans des sections du système de fichiers dont il n'aurait a
priori pas l'usage. Il s'agit donc conceptuellement d'une sorte de v irtualisation.
N amespaces étend ce concept à d 'autres ressources.
Namespace Isole
IPC Communication interprocessus
Network Terminaux réseau, ports, etc.
Mount Point de montage <système de fichiers)
PID Identifiant de processus
User Utilisateurs et groupes
l:J
UTS Nom de domaines
0
c
::J
~
.
.,
"O
0 c::;
\.0
.-t
0
.,.,
~
N
·~
@ ·c
B
1.2.4 Qu'est-ce qu'un conteneur finalement ?
....... ::;
..c: CO
Ol c
ï:::: 0
c Un conteneur est tout simplement un système de fi chiers sur lequel s'exécutent des
>- c
o.. processus (de préférence un par conteneur) de manière :
u
0 ·3
<.)
::;
"O
0
..... • contrainte : grâce à CGroups qui spécifie les limites en termes de ressources ;
c.
~
~
• isolée : grâce notamment à Namespaces qui fait en sorte que les conteneurs ne
::;
rS se voien t pas les uns les autres.
1
"O
0
c
8
(Ç)
8------------------- Chapitre 1. Les conteneurs et le cos Docker
C omme nous l'avons précédemment expliqué, les conteneurs existent depuis long-
temps, mais Docker a apporté des n ouveautés décisives qui ont clairement favorisé
leur popularisation .
L'une d 'entre elle a trait à la manière don t Docker optimise la taille des conteneurs
en permettant une mutualisation des données. C 'est ce que nous allons expliquer dans
cette section.
N ous allons aussi aborder la question de la persistance des données dans un
conteneur, en expliquant la notion de volume.
Notez que nous expérimenterons ces concepts ultérieurement, à l'aide des outils
Docker.
La n otion d'image dans le monde conteneur est pratiquement synon yme de Docker.
Comme n ous l'avons déjà vu, un conteneur est un ensemble de fichiers sur lequel
s'exécutent un ou plusieurs processus. O n peut alors se poser la question suivante :
mais d'où v iennent ces fichiers ?
Construire un conte neur pourrait se faire à la main, en reconstruisant dans une
partie du système de fichiers Linux une arborescen ce de fichiers : par exemple, un
réperto ire pourrait stocker les fichiers spécifiques au conteneur qui ne font pas partie
l:J
0
c du n oyau de l'OS. Mais cette p ratique serait fastidieuse et poserait le problème de la
::J
0 distribution e t de la réutilisation.
\.0
.-t
0 L'un des apports essentiels de Docker est d'avoir proposé une manière de condi-
N
tionner le contenu d'un con teneur en blocs réutilisables et échangeables : les images.
@
.......
..c: Ces images sont don c des archives qui peuvent être échangées entre plusieurs hôtes,
O'l
ï:::: mais aussi être réutilisées. C ette réutilisation est rendue possible par une seconde
>-
0..
0 innovation: l'organisation en couches.
u
Les contene urs Docker sont en fait des millefeuilles constitués de l'empilement
ordonné d'images. Chaque couche surcharge la précédente en y apportant éventuelle-
ment des ajouts e t des modifications.
1.3 Les apports de Docker: structure en couches, images, volumes et registry ---------a
En s'appuyant sur un type de système de fichiers Linux un peu particulier nommé
Union File System 1 , ces différentes couches s'agrègent en un tout cohérent : le
conteneur ou une image elle-même réutilisable.
L'application elle-même
Conteneur éventuellement associée à des
fichiers de ressources (images,
configuration, etc.)
Application
Des bibliothèques logicielles dont
i...J..--- - - - dépend l'application (Jar pour java,
Bibliothèques logicielles gems pour Ruby, etc.)
li
L'image de base du conteneur
généralement fournie par Docker.
OS hôte Par exemple: CentOS 7.
Elle contient les packages
fondamentaux spécifiques de /'OS
du conteneur.
j Infrastructure
Hôte
Admettons que nous construisions une application s'appuyant sur deux conteneurs
tournant sur le même hôte :
• un front-end basé sur une application JSP, tournant dans un serveur d'applica-
tions Tomcat2, exécuté par une machine virtuelle Java 1.8 sur un OS CentOS 7 ;
"'Cl
0
c ~
• un back-end constitué d'une base de données Cassandra3 s'exécutant elle aussi
:::i ,.,
0 "O sur Java 1.8 et CentOS 7.
[Link];
\.0
.-t ~
0
N
V
V Lorsque nous allons installer le front-end (nous verrons comment par la suite), le
'ii
@ ·c système va charger plusieurs couches successives qui sont autant de blocs réutilisables.
....... B
..c
:::;
CO Lors de l'installation du conteneur de base de données, le système n'aura pas à charger
O'l c
ï::::: 0
c l'image CentOS ou la machine virtuelle Java, mais uniquement les couches qui sont
>-
o. c
0 ·3ù spécifiques et encore absentes du cache de l'hôte.
u :::;
"O
0
....
c.
~
~
:::;
rS l. Nous verrons dans la suite de ce ch apitre qu'il existe plusieurs implémentations de ce type de
1
"O
0 système de fichiers.
c
8 2. [Link] [Link]/
(Ç) 3. [Link]
8------------------- Chapitre 1. Les conteneurs et le cos Docker
OpenJDK 1.8
1 Infrastructure 1
Hôte
Attention la représentation donnée des couches d'images dans la figure 1.8 est très
simplifiée. En réalité, une image de base CentOS 7 est, par exemple, constituée
"'Cl
0
de quatre couches. Mais le principe exposé d'empilement et d'agrégation de ces
c couches par l'intermédiaire d'un union file system reste le même.
:::i
0
\.0
.-t
0
N
@ 1.3.3 Docker Hub et registry
.......
..c
O'l
ï:::::
Dans le paragraphe précédent, nous avons exposé les fondements de la structure d'un
>-
0. conteneur. Nous avons notamment évoqué la manière dont l'hôte pouvait charger des
0
u blocs d'images constituant les conteneurs.
Mais à partir d'où un hôte Docker va+il charger ces blocs?
C'est le rôle d'un autre composant essentiel de l'architecture Docker: le registry.
Le registry est l'annuaire et le centre de stockage des images réutilisables. Sa
principale instanciation est le Docker Hub public et accessible v ia l'URL [Link]
[Link]/.
1.3 Les apports de Docker : structure en couches, images, volumes et registry ----------a
..... Oashboard f xplorr Organ11at1ons Q rrr>atr • pycloux
pycloux M Repositories * Stars Ci!' Contnbuted Private Repositories Using 0 of 1 Get more
Docker Trusted
Registry
pycloux/test
public
0 0 > Need an on-premise
registry? Gel a 30-day
STARS PULLS ::TAL
free tnal
OFFICIAL REPOSITORY
centos {::[
l:J
0
c
::J
~
,., Short Description Docker Pull Command
"O
0 c::; The official build or centos. docker pull centos
\.0
.-t
0
.,.,
~
N
'~ Full Description
@ ·c
....... B::;
..c: CO
Ol
ï:::: 0
c
c
Supported tags and respective
>- c
o..
u
0 ·3
<.)
Dockerfile links
::;
"O • latest centos7 , 7 (docker/Dockerfrle)
0
..... centos6 , 6 (docker/Dockerfile)
c. •
~ • centos5 , 5 (docker!Dockerfî/q)
~ • centos7. 2 .1511 7. 2 .1511 (docker/Dockerfîle)
::;
rS
1
"O
0
Figure 1. 1 0 - Image de base CentOS
c
8
(Ç)
8------------------- Chapitre 1. Les conteneurs et le cos Docker
Mais il faut comprendre que le Docke r Hub n'est qu'une instanciatio n publique
d'un registry. Il est tout à fait possible à une entreprise d'installer un registry privé 1
pour y gérer ses propres images.
Cache local
Repository X
Image locale
Docker engine
Registry
Hôte
l. Docker propose d'ailleurs un logiciel nommé Docker Trusted Registry pour les clients qui souhaitent
mettre en place leur propre instance.
2. [Link] er-registry/
3. h ttps://[Link]/fr/ecr/
1.3 Les apports de Docker : structure en couches, images, volumes et registry ---------a
La réutilisation des images se produit donc de deux man ières:
• à l'éch elle d'un hôte, par l'intermédiaire du cach e local qui permet d'économiser
des téléch argements d'images déjà présentes ;
• à l'échelle du registry, en offran t un moyen de partage d'images à destination de
plusieurs h ôtes.
Le container layer
Intuitivement, on comprend que ces données sont produites dans une couch e au~dessus
de toutes les autres, qui va être spécifique au conten eur en cours d'exécution. Cette
couch e se n omme la couche de conten eur (ou con tainer layer ).
r----- -----,
I_ Couche
1 du conteneur A I1L
___________ 1 Couche du conteneur B- 1
__________ 1
l:J
0 Cl5aceaa7:e96a
c
::J
~
,.,
"O
0 c::; Les couches de l'image
\.0 atfüoa9 ~ 63c9t5 à partir de laquelle le
.-t
0
.,.,
~
conteneur est «créé».
N Ces couches ne sont
'~
@ ·c e55 ~~ 5l:lc2~f pas modifiables, elles
....... B
::;
..c: CO
sont en «lecture seule».
Ol c
0
ï:::: c a33f3c9e c
>- c
o..
u
0 ·3
<.) lmageXYZ
::;
"O
0
.....
c.
~
~
Figure 1. 1 2 - Couches d'images et couches de conteneurs
::;
rS
1
"O
0
C ette couch e de conten eur est modifiable contrairement aux couch es d 'images
c
8 qui n e le sont pas. Dans le cas contraire, faire tourner un conten eur reviendrait à
(Ç) altérer poten t iellement l'image sur laquelle il est construit, ce qui n'aurait aucun sen s,
8 -------------------- Chapitre 1. Les conteneurs et le cos Docker
puisque le but d'une image est justement de pouvoir créer autant de conteneurs que
l'on souhaite, à partir du même moule.
Soit, mais imaginons que nous construisions un conteneur à partir d'une image de
base CentOS. Imaginons encore que nous souhaitions modifier la configuration de
ce système de base, par exemple /etc/bashrc, qui configure l'env ironnement du shell
UNIX bash . Si l'image de base n'est pas modifiable, comment allons,nous pouvoir
procéder ?
11 1
Couche du conteneur A 11
Couche du conteneur B 1
1: ~ 1 La version «modifiée• du
:1 /etc/bashrc ~ fichier« /etc/bashrc» qui
: devient la version courante
______________1 1
- _ _ _ _ _ _ _ _ _ _ _ _ _ pour le conteneur B.
La version originale du
fichier « /etclbashrcit qui est
--------1-1- initialement commune à
tous les conteneurs et reste
la version en place pour le
conteneur A
l:J
0 Image XYZ
c
::J
0
\.0
.-t
0 Figure 1. 1 3 - Concept de copy on wtite <COW>
N
@
.......
..c:
O'l
ï::::
En réalité, l'image n'est pas altérée, mais lorsqu'une modification est demandée sur
>-
0.. un élément d 'une image, le fichier original est copié et la nouvelle version surcharge
0
u la version originale. C'est le principe du copy on write. Tant que les accès ne se font
qu'en lecture, c'est la version initiale (issue de l'image) qui est employée. Le COW
n 'est appliqué que lors d'une modification, ce qui optimise de fait la taille de la couche
du conteneur qui ne comprend que le différentiel par rapport à l'image.
Le principe est le même pour les effacements de fichiers de l'image. La couche
conteneur enregistre cette modification et masque le fich ier initial.
1.3 Les apports de Docker: structure en couches, images, volumes et registry --------a
En réalité, l'explication ci,dessus est quelque peu simplifiée. La manière de gérer
l'union des couches et le copy on write dépend du pilote de stockage (storage driver)
associé à Docker. Certains travaillent au niveau du fichier, d'autres au niveau de
blocs plus petits. Mais le principe reste identique.
Persistance et volumes
Que se passe't'il quand un conteneur s'arrête ?
La couche de conteneur est tout simplement perdue. Si cette couche comprend
des données à conserver entre deux lancements de conteneurs ou bien à partager entre
plusieurs conteneurs, il faut utiliser un volume (ou data volume).
r-----------~r-----------,
1_ Couche
1 du conteneur A 1I 1L Couche
___________ du conteneur B 1
___________ 1 Un volume (monté dans les
conteneurs sous la forme
/opUshared d'un répertoire) qui va
,.........;=======================~ stocker les données sur
l'hôte ou sur d'autres
systèmes de persistance.
l:J
0
c
::J
~
,.,
"O
0 c::;
\.0 lmage XYZ
.-t
0
.,.,
~
N
'~
@ ·c
....... B::;
Figure 1.14 - Volumes
..c: CO
Ol c
ï:::: 0
>- c Les volumes sont des espaces de données qui court,circuitent le système d'union file
o.. c
u
0 ·3
<.)
que nous avons évoqué précédemment. Ils sont modifiés directement et les données
::;
"O
0
.....
qui y sont inscrites surv ivent à l'arrêt du conteneur. Ce sont des systèmes de fichiers
c.
~ montés dans le conteneur qui, selon les implémentations, reposent :
~
::;
rS • sur un espace disque de l'hôte gere par Docker (stocké sous
"O
1
/var/lib/docker/volumes/ mais pas modifiables directement) ;
0
c
8 • sur un répertoire de l'hôte directement monté dans le conteneur et qui permet
(Ç) de créer un pont entre l'hô te et le conteneur ;
El------------------- Chapitre 1. Les conteneurs et le cos Docker
• sur un large panel de systèmes tiers qui imposent l'usage d'une extension (volume
plugin) particulière 1•
Les volumes sont un concept important dans le domaine des conteneurs Docker.
Nous les aborderons en détail au cours de nos d ifférents exemples pratiques dans la
suite de cet ouvrage.
..
1.4 LES OUTILS DE L'ECOSYSTEME DES CONTENEURS :
DOCKER ET LES AUTRES
Nous avons vu précédemment ce qu'était un conteneur, comment il é tait structuré
(du moins dans le cas de Docker) et comment il était distribué.
N ous allons maintenan t fournir une vue générale des outils qui gravitent autour de
la technologie des conteneurs. Nous souhaitons ici montrer les logiciels qui permettent
d 'exécuter des con teneurs sur une mach ine ou sur plusieurs machines en réseau.
N ous ne nous limiterons pas au cas des outils de la société Docker lnc., mais nous
présenterons aussi d 'autres acteurs. L'objectif pour le lecteur est d 'arriver à se repérer
dans ce foisonnement de produits et d 'en comprendre les position nements respectifs.
Nous noterons que toutes ces implémentations (et il en existe d'autres plus
confidentielles) sont compatibles avec le format d'image Docker.
1. [Link]
2. [Link]
3. h ttps://[Link] ped [Link]/wiki/Wi ndows_Server_2016
1.4 Les outils de l'écosystem e des conteneurs : Docker et les autres ------------[!!]
• à définir un ordre de démarrage (directement ou indirectement) ;
• à définir les systèmes de fichiers persistants (les volumes) ;
• à définir les liens réseau que les conteneurs vont entretenir entre eux (ou du
moins à assurer une communication transparente entre les processus).
Hôte
Descripteur \ Conteneur A
1 û .. .___ o_ut-il_d_e___
composition
Moteur de
conteneur
- - -----.\ Conteneur 8
Il est bien évidemment possible de démarrer les conteneurs à la main à l'aide d'un
script exécutant des séries de docke r run .
Mais cette solut ion peut rapidement deven ir complexe. En effet, il faut aussi tenir
compte de l'éventuel besoin de distribuer la charge sur plusieurs nœuds du réseau et
plusieurs machines. Il faut donc que la composition puisse s'effectuer en collaboration
avec des o utils de clustering réseau q ui vont abolir les frontières e ntre les d iffé rents
hôtes. On parle alors d'orchestration .
r Hôte 1 ~
l:J
Exemple:
Docker Swarm ' ----7\ Conteneur A """
0 Outil de Moteur de
c ~
,., clustering
-\ Conteneur B
::J conteneur
..
"O
0 c::;
\.0 Descripteur t Exemple: ~\ Conteneur C
.-t
0
.,.,
~
DockerEngine
N
@
.......
..c:
Ol
·;::
'~
·c
B
0
::;
CO
c
c
i
Exemple:
Outil de
compos ition
Exemple:
\...
'
Hôte2
./
"""
- ..
>- c fichier YAML Docker Compose ----7\ Conteneur A
o.. "Compose"
u
0 ·3
<.)
::; Moteur de :;..\ Conteneur B
"O
0
..... conteneur
c.
~
~
Exemple: ~\ Conteneur C
::;
DockerEngine
rS \..
"O
0
1
\... ~
c
8 Figure 1. 16 - Clustering + composition = orchestration
(Ç)
El-------------------- Chapitre 1. Les conteneurs et le cos Docker
En résumé
Dans ce chapitre, nous avons appris ce qu'est un conteneur, sur quelles briques
fondamentales les conteneurs Linux sont basés, commen t ils sont structurés dans le
cas de Docker et comment ils sont distribués.
Nous avons ensuite abordé les différents outils assurant leur exécution: moteurs de
conteneurs, systèmes d'exploitation spécialisés, outils de composition et d'orchestra-
tion.
Il est maintenant temps d'étudier l'apport de ces outils aux techniques d'automatisa-
tion de l'explo itation d'une infrastructure d'applications. Notre prochain chapitre
va montrer comment ces briques de base s'agrègent aujourd'hui dans divers types de
solutions industrielles.
Nous expliquerons aussi comment ces solutions à base de conteneurs se positionnent
par rapport à des solutions de gestion de configuration comme Puppet, A nsible ou
Chief.
l:J
0
c
::J
0
\.0
.-t
0
N
@
.......
..c:
O'l
·;::
>-
0..
0
u
2
Conteneurs et infrastructures
L'automatisation de 1'exploitation
L'objectif de ce ch apitre est de montrer comment les conteneurs se positionnent
comme une nouvelle opportunité pour automatiser le déploiement et l'exécution des
applications dans les entreprises. Nous allons aborder la notion de CaaS (Container as
a Service ) mais aussi t enter d e positionner la technologie des con ten eurs par rapport
à d'autres solutions d'automatisation de la gestion de configuration , comme Puppet
ou Ansible.
Pour ce qui est des infrastructures publiques CAmazonEC2, Google, Windows Azure,
Heroku, Digital Ocean, etc.) le principe est identique, si ce n'est que les solutions sont
propriétaires, tout en étant ouvertes via des services web documentés.
[in,age de machine 1
L virtuelle
~
Services d'infrastructure
Réseau
Stockage Sécurité
l:J
0 Ressources physiques
c
::J (machines. disques. routeurs. etc.)
0
\.0
.-t
0
N Figure 2.1 - Services d'infrastructure d'une solution laaS
@
.......
..c:
O'l
·;::
>- Pour peu qu'une application soit conditionnée sous la forme d'une ou plusieurs
0..
0 machines virtuelles, elle bénéficie des ressources dont elle a besoin sans avoir à se
u
soucier de la gestion de la qualité de service liée à l'infrastructure.
En effet, les solut ions laaS vont détecter les failles matérielles (voire les anticiper)
et s'assurer que l'environnement d 'exécut ion est toujours actif. S i une machine
ph ysique casse, les machines v irtuelles qu'e lle exécute à un instant donné peuvent
être transférées de manière quasi transparente sur un autre hôte.
Mais alors que vont apporter les conteneurs aux solutions laaS ?
2.1 Automatiser la gestion de l'infrastructure : du laaS au CaaS - - - - - - - - - - - - - a
2.1 .2 Le conteneur n'est-il qu'un nouveau niveau de virtualisation ?
Les conteneurs, et Docker en particulier, sont donc au centre d'une nouvelle gamme
de solutions que certains nomment CaaS pour Container as a Service qui fait écho à
l'laaS que nous avons évoqué précédemment.
En quoi l'utilisation de conteneurs change-t-elle la donne ?
Pratiquement, les conteneurs ne changent pas les solutions laaS qui conservent
leurs avantages propres, mais ils peuvent s'appuyer sur elles pour les étendre et offrir
de nouvelles opportunités.
Nous avons vu dans le chapitre 1 ce que pouvait apporter la virtualisation à base de
conteneurs par rapport à la virtualisation matérielle. Il ne s'agit pas d'une alternative
technologique, mais bien d'une autre manière de concevoir le lien entre le développeur
et l'exploitant.
Pour comprendre, analysons le processus de préparation d'en vironnement, puis le
processus de déploiement d'une application dans un en vironnement laaS.
l:J
0
c
::J
~
,., exploitant
"O
0 c::;
\.0
.-t
0
.,.,
~ laaS
N
'~
@ ·c
....... B::;
..c: CO
Ol c
ï:::: 0
>- c
o.. c
u
0 ·3
<.)
Runtime
::;
"O
0
.....
c.
~
~
::;
développeur
rS
1
"O
0
c Figure 2.2 - Préparation de lenvironnement
8
(Ç)
El-------------------- Chapitre 2. Conteneurs et infrastructures
Techniquement, le paquet logiciel peut être un zip, un tar, un msi (dans le monde
Microsoft), un rpm (dans le monde Linux Fedora), le choix étant vaste. À ce ou ces
paquets sont souvent associés des scripts de déploiement plus ou moins normalisés
qui sont souvent écrits par l'exploitant (en collaboration plus ou moins étroite avec
l'équipe de développemenù.
--111 1 111~
Code Paquet
Build
source logiciel
l:J
0 développeur
c
::J
0
\.0
.-t
0
N
exploitant
@
.......
..c:
O'l
·;::
déploiement
>-
) @
[=·r
0..
0
u
Attention, nous ne disons pas qu'il est impossible d'adopter une approche visant à la
reconstruction systématique de l'environnement d'exécution. L'usage de templates
d'application et d'outils automatisés de gestion de configuration (tel que Vagrant
parmi d'autres déjà cités) rend possible ce type de modèle avec des machines
virtuelles classiques. Mais reconnaissons que ce type de cas est rare dans un
environnement de production. La plupart du temps, il y a une différence claire
entre la construction de l'environnement (ou sa modification) et le déploiement
d'applications.
image Règles
développeur
d) 1__s_~0_u~-c~_I @ ~ Build +
de
gestion
@
l
exploitant
l:J
Enfin, les solutions C aaS associent au déplo iement des règles de gestion. C elles-ci
0 peuvent prendre la forme d'un fichier YAML ou JSON, selon les solutions. C elui-ci
c
:J
0 peut être produit par l'équipe de développement ou être élaboré en collaboration avec
\.0
.-t l'exploitant. C ette configuration va spécifier d'une manière totalement formelle les
0
N caractéristiques non-fonctionnelles de l'architecture :
@
....... • n ombre d'instances de chaque type de conteneur ;
..c:
O'l
·;:: • liens entre les con teneurs ;
>-
0..
0 • règles de montée en c harge ;
u
• règles de répartit ion de ch arge ;
• volumes persistants ;
• etc.
Sans entrer dans le détail, on n ote que le fichier va spécifier des informations
concernant :
• les règles de déploieme nt (par exemple ro 11 i ng Update qui explique que les
l:J
0 différents nœ uds de l'application doiven t être mis à jour les uns après les autres) ;
c ~
,.,
0
::J
"O • les caractéristiques de l'architecture en termes de nombre d'instances ( repli cas )
c::;
\.0 et de politique de redémarrage ( res t a rtpo l i cy ).
.-t
0
.,.,
~
N
'~
@ ·c N ous allons expliquer le mode de fonctionnement dynamique des solutions C aaS
....... B
..c:
::;
CO sur la base de ce type de règles de gestion dans la section suivante .
Ol c
ï:::: 0
>- c
o.. c
0 ·3 À première vue, cette programmabilité complète de l'infrastructure semble séduisante.
u <.)
::; Elle a cependant un coût : l'application doit être conçue dès son origine pour
"O
0
.....
c. fonctionner dans un mode conteneur ou micro-services. Ce sera l'objet des chapitres
~
~
suivants d'expliquer la manière de concevoir une image Docker et comment celle-ci
::;
rS peut être assemblée à d'autres images pour produire une application container-ready.
1
"O
0
c
8
(Ç)
El-------------------- Chapitre 2. Conteneurs et infrastructures
Les solutions CaaS ont un certain nombre de caractéristiques communes qu'il est bon
de connaître :
• e lles incluent presque toutes Docker (en dehors de celle de CoreOS qui lui
préfère Rkt) en tant que moteur de conteneurs;
• elles fournissent des fonctions de clustering et d'orchestration (décrites dans
le chapitre précédent et qui seront abordées en pratique dans la suite de cet
ouvrage);
• e lles s'appuient sur un principe de gestion automatisée de l'infrastructure que
nous qualifierons d'ho méostatique.
l:J
0
c ~
,.,
R
g Règlesde
gestion
Contrôleur ....
::J
"O
0
\.0
c::; . . . . 1 Agent
.-t
0
.,.,
~
N
'~
@ ·c Les règles de gestion décrivent Un contrôleur central va
....... B::;
..c: CO l'état souhaité pour le système: surveiller l'état des différents
Ol c
ï:::: 0
c
• nombre d'instances de nœuds du système et
>- c chaque type de conteneur déclencher des actions
o..
u
0 ·3
<.) règles de gestion de charge automatiques pour s'assurer
::;
"O
0
..... • Etc. que la réalité rejoigne à chaque
c.
~ instance la description
~ «programmée».
::;
rS
1
"O
0
c Figure 2.5 - Principe de fonctionnement des CaaS
8
(Ç)
8-------------------- Chapitre 2. Conteneurs et infrastructures
Les règles expriment des exigences, l'état cible souhaité et le système s'assure au
travers d'actions déclenchées automatiquement que cet état soit atteint et maintenu
autant que possible. D'autres solutions que nous aborderons dans la dernière section,
comme Ansible, fonctionnent sur le même principe.
1. h ttp://[Link] [Link]/
2.2 Les solutions CooS --------------------------8
2.2 LES SOLUTIONS CAAS
N ous allons maintenant aborder quelques-unes des solutions emblématiques de ce
phénomène C aaS. Attention, il est important de bien intégrer le fait que ce nouveau
marché est en pleine construction. Aucune des solutions décrites ne recouvre
complètement les autres d'un point de vue des fonctionnalités offertes. C ertaines
affichent même la possibilité de collaborer ou de s'intégrer avec d 'autres. Mais, ne
nous y trompons pas, la compétition est féroce et c'est à une course de v itesse que se
livrent les principaux acteurs de ce marché.
O utre le Docker Engine, la société Docker lnc. édite d'autres logiciels. Certains ont
été développés en interne, tandis que d'autres ont été rachetés à d 'autres sociétés
(comme Compose ou Tutum, par exemple ).
Docker travaille activement à la consolidation de ces différents outils en une suite
cohérente : Docker Datacen ter.
L'objectif de Docker est de proposer une suite supportant d 'un bout à l'autre le
cycle de développement, déplo iement et opération.
Universal contrai ••
~I
D plane
Docker compose 1
.
....
~~
l:J Toolbox Registry
0
c
:i
0
~~-~I
Les développeurs Les images sont publiées
\.0
.-t construisent les images sur sur le registry privé de
0 leur environnement local
N l'entreprise. Les transferts
@ d'images sont sécurisés par
....... des mécanismes de
..c signature supportés par Docker Swarrn
en
·c Docker Notary.
Grace à l'UCP et la suite
>-
0. Docker, les opérations
0
u gèrent l'infrastructure
d'exécution des conteneurs.
l. h ttps://[Link]/producrs/docker-swarm
2. [Link]
3. [Link]
4. [Link]
2.2 Les solutions CooS --------------------------8
Comment ça marche ?
Chaque hôte de l'architecture exécute un agent Swarm. C et hôte constitue alors
un Swarm node. L'agent offre une interface de contrôle (et de surveillance) au point
central de pilotage du cluster swarm : le manager.
Le manager est le service qui expose l' API de contrôle du cluster. Il peut être
télécommandé en ligne de commande (Docker CU) ou bien via le Docker UCP (une
interface web).
Notez qu'en production on aura généralement plusieurs master nodes <pour des
raisons de haute disponibilité). Dans ce cas, plusieurs managers sont installés et la
résilience de l'ensemble est assurée par la réplication de l'état de ces managers, par
exemple au travers d' etcd.
Universal control
DockerCLI
plane
~~---------- ---------~,
I
~
Hôte 3
''
I Swarm manager S\varrn master \
node
..
Swarm Swarm Swarm
l:J
0
0
c
::J
~
.
.,
"O
c::;
....
agent
-~
......
agent
-~ -~
agent
~
\.0
.-t
0
.,.,
~
Il est aussi possible de déclarer des relations d'affinité plus ou moins complexes. Par
exemple, vous pouvez vous assurer que les conteneurs base de données ne sont créés
que sur les nœuds qui possèdent des disques SSD haute performance.
Grâce à cette bibliothèque de règles (qui va probablement s'enrichir au fil du temps)
Swarm offre la possibilité de configurer un large panel d'architectures applicatives et
de stratégie de gestion de charge.
A Dashboard Dashboard
Overvfew
Applications
111§5
Nodes
Volumes
1 24 41 2
Networks
Resources
Images
~p'
Users & Teams
Settings
l:J
0
0
c
::J
\.0
.-t
0
N
@
Cluster Controllers
ml
""
hrtpsl/17 314101"443 tcp://172.31 .4 101 :2376 etCd'.1/172.31.4. 101 :12379
.......
..c:
O'l
·;:: Figure 2.8 - UCP, le cockpit graphique de l'écosystème Docker
>-
0..
0
u
2.2 Les solutions CooS --------------------------8
Certains auront peut,être entendu parler du projet open source Shipyard 1 qui
propose aussi une interface d'administration graphique pour les outils Docker.
Aujourd'hui, Shipyard offre une alternative vraiment intéressante à UCP pour
les petits budgets. Néanmoins, au fil des nouvelles versions, il est probable que
Docker enrichisse son offre de fonctionnalités plus avancées et moins ouvertes
(UCP n 'est en effet pas un projet open source).
La suite CaaS de Docker n'est pas la seule sur le marché. D'autres solutions offrent
des fonctionnalités similaires, tout en s'appuyant néanmo ins presque systématique,
ment sur le moteur de Docker.
Kubernetes 2 est un projet open source initié par G oogle. Contrairement à ce qui est
souvent écrit, G oogle n'utilise pas Kubernetes en interne, mais un autre système
nommé Borg. N éanmoins, Kubernetes a clairement bénéficié de l'expérience de
Google dans la gestion de centres de calculs et d'applications distribuées hautement
disponibles. Notons que G oogle utilise des conteneurs depuis près de dix ans, ce qui
explique pourquoi la plupart des technologies de base des conteneurs (notamment
CGroups et Namespaces) ont été élaborées par des ingénieurs de Google.
Kubernetes s'appuie sur le moteur de Docker pour la gestion des conteneurs3 . Par
contre, il se positionne comme une alternative à Docker Swarm et Docker C ompose
pour la gest ion du clustering et de l'orchestration.
Dans les faits, G oogle ne souhaite probablement pas concurrencer Docker sur le
terrain de l'édition de logiciels, mais utilise Kubernetes pour promouvoir son offre
Cloud CaaS, nommée Google container engine4. C e produit, qui s'intègre dans son offre
de cloud public (certainement la plus riche du marché après celle d'Amazon), est
justement basé sur Kubernetes, sa ligne de commande et son format de descripteur.
"'Cl
0 L'architecture de Kubernetes
c
:::i
~
,.,
"O
0 [Link]; La figure ci,dessous présente une architecture synthétique de Kubernetes. On y
\.0
.-t ~ distingue notamment les deux composantes habituelles des CaaS :
0 V
N V
'ii
@ ·c • un contrôleur central, chef d'orchestre du système, ici nommé kubemetes control
....... B
..c
:::;
CO plane qui, comme pour Swarm, peut stocker sa configuration dan s un cluster
O'l c
ï::::: 0
c etcd;
>-
o. c
u
0 ·3ù
:::;
"O
0
....
c.
~
~ 1. [Link]
:::;
rS 2. h t tp://[Link]/
1
"O
0 3. Kubernetes a aussi pour objectif de s'ouvrir à d'autres moteurs, n otamment RKT, le moteur de
c
8 conteneurs de CoreOS.
(Ç) 4. [Link] .[Link]/containeHngine/
El--------------------- Chapitre 2. Conteneurs et infrastructures
• un ou plusieurs nœ uds (ou node) qui hébergent les agents Kubem etes, que l'on
nomme également kubelets, et évidemment, les conteneurs organisés en pods 1•
Node
Kubelet
Authentification
API server
Controller
Scheduler
Manager
Stockage de
configuration ..
~~
Pod
..
Pod
(1•
- (\
Oockerengo~
Les kubelets sont les agents qui contrôlent les conteneurs qui sont regroupés en pod
l:J
dont n ous allons évoquer les caractéristiques un peu plus bas. Ces kubelets contrôlent le
0
c cycle de vie des conteneurs et surveillent leur état (en utilisant notamment cAdvisor2
:i
0 en lien avec le moteur Docker). On trouve aussi sur chaque nœud un autre composant
\.0
.-t important: le kube~proxy.
0
N
Le kube~proxy est un proxy répartiteur de charge (load balancer) qui gère les règles
@
....... d'accès aux services (la plupart du temps des interfaces http/https) offerts par les pods,
..c
en
'i:
mais à l'intérieur du cluster Kubemetes uniquement. Ce dernier point est important
>- et nous y reviendrons dans la prochaine section.
0.
0
u Les kube,proxies sont mis à jour chaque fois qu'un service Kubernetes est mis à
jour (qu'il soit créé ou que son implémentation ait changé de place) et ils permettent
1. Pod, que l'on pourrait traduire en français par réceptacle ou enveloppe, désigne un groupe
de conteneurs qui collaborent étroitement pour fourn ir un service donné. Ils vont donc, dans
l'arch itecture Kubernetes, pouvoir communiquer entre eux sans intermédiaires.
2. [Link]
2.2 Les solutions CooS --------------------------8
aux conteneurs de s'abstraire de la localisation réelle des autres conteneurs dont ils
pourraient avoir besoin.
On n otera que le Kubem etes Control Plane est en fait constitué de plusieurs sous-
composants :
• un serveur d'API REST « API server », qui est notamment utilisé par Kubectl,
la ligne de commande Kubem etes qui permet de piloter tous les composants de
l'architecture ;
• le sch eduler, qui est utilisé pour provisionner sur différents nœ uds (node) de
nouveaux pools de conteneurs en fonction de la topologie, de l'usage des
ressources ou de règles d 'affinité plus ou mo ins complexes (sur le modèle des
stratégies Swarm que nous avons évoquées précédemment). Dans le futur,
Kubem etes affirme vouloir s'ouvrir à différentes implémentations, v ia un
mécanisme de plugins, probablement pour prendre en compte des règles de
plus en plus sophistiquées ;
• le controller manager, qui exécute les boucles de contrôle du système ou controllers
(à une fréquence déterminée) pour vérifier que les règles de gestion programmées
sont respectées (no mbre d'instances de certains conteneurs, par exemple).
N
·~ Modèle réseau Kubernetes
@ ·c
B
.......
..c:
::;
CO
En réalité, le modèle réseau de Kubernetes va encore plus loin. Chaque pod est
Ol c associé à une adresse IP unique. De plus, l'espace d'adressage à l'intérieur d'un cluster
ï:::: 0
>- c
o.. c Kubernetes est plat, c'est-à-dire que tous les pods peuvent se parler en utilisant ladresse
u
0 ·3
<.)
::; IP qui leur a été allouée sans avoir recours à de la translation d'adresse <NAT ou
"O
0
.....
c.
Network Adress Translation).
~
~
Cette pratique facilite l'implémentation de clusters multi-hôtes, mais diffère notablement
::;
rS du modèle réseau par défaut de Docker qu'il est néanmoins possible de changer. C est
"O
1
d'ailleurs ce qu'offre Swarm en créant un moteur Docker au travers de plusieurs hôtes.
0
c
8
(Ç) S i un pod est une instan ce de micro-service, alors qu'est-ce qu'un micro-service ?
a Chapitre 2. Conteneurs et infrastructures
Service Service
front - end back-end
Node1
Kube-proxy
Pod
front - end
Pod
back-end
External
HTIPIHTIPS
load balancer
Node2
Kube-proxy
Pod Pod
front-end back- end
1. Round robin est un algorithme de répartition de traitement dans lequel les processus participants
sont sollicités à tour de rôle.
2.2 Les solutions CooS --------------------------[!!]
• load balancing de niveau 7 ;
• affinité de session ;
• etc.
Mesos a une vocation plus large qu'un CaaS classique, dans la mesure où il est
apparu avant la vague Docker. Mesos offre n otamment un concept de framework qui
lui permet de se brancher sur diverses solutions de contrôle, notamment Kubernetes,
mais aussi Marathon, la solution maison de gestion de con teneurs.
En pratique, on retrouve exactement la même architecture conceptuelle :
• un mesas master (éventuellement répliqué dans le cadre d'une architecture à
haute disponibilité) ;
• des mesos slave qui hébergent les agents qui vont exécuter les ordres émis depuis
le master et fournir des informations en temps réel sur l'état des hôtes.
l:J
0
c Tout comme les solutions précédemment étudiées, Mesas/Marathon va utiliser
:J
0 divers algorithmes pour mettre en correspondance les ressources ( CPU, RA M ou
\.0
.-t autre) disponibles dans l'infrastructure et les demandes d'exécution s d'applications
0
N (synchrone ou batch) .
@
.......
..c: À l'inverse des solutions pure C aaS, comme Kubernetes ou Swarm, Mesos peut
O'l
·;:: aussi utiliser d'autres technologies de déploiement et d 'exécution. En plus des
>-
0.. framework Marathon ou Kubernetes, Mesas peut utiliser:
0
u
• des schedulers classiques, comme Jenkins ou Chronos (qui peuven t donc exécuter
n'importe quel type de commande) ;
• des solutions Bigdata, comme H adoop ;
• des solutions de stockage de données, comme Cassendra.
2.2 Les solutions CooS --------------------------[!!]
2.2.4 Fleet + Rkt + Etcd : la solution de CoreOS
La solution de CoreOS est présentée très sommairement au travers de la figure 2.12.
C elle-ci, quo ique complète et open source, est probablement plus confidentielle que
celles que nous avons citées précédemment.
Système d'exploitation
spécialisé pour les hôtes de
conteneurs
Solution de clustering
Équivalent: Boot2dockerou
Atomic .J Équivalent: Swarm
l:J
0 Google Container Engine
c
:i
~
,.,
"1:l
0 c;:; Il y a peu de chose à ajouter sur cette offre lancée par G oogle en novembre 2014, si
\.0
.-t
0
~
V
ce n'est qu'elle s'appuie évidemment sur Kubernetes, projet open source financé et
N V
'& promu par le géant californien.
@ ·c
....... B;:;
..c CO
en
ï:::::
c
0
Amazon ECS, l'autre offre cloud
>- c
o. c
0 ·3 Amazon a lancé son offre Amazon EC2 Container Service (ou ECS) en novembre 2014.
u <.)
;:;
C ette offre ne s'appuie ni sur Kubernetes, n i sur la suite de Docker. Amazon a tout
"1:l
0
.....
c.
~
simplement fabriqué sa propre solution .
2:l;:;
Celle-ci s'appuie sur un agent open source 1 , mais sur un contrôleur qui, lui, ne
rS
1 l'est évidemment pas, puisqu'il est uniquement implémenté par Amazon EC2 (dans
"1:l
0
c
8
(Ç) 1. h ttps://gi [Link]/aws/a mazon-ecs-agent
El-------------------- Chapitre 2. Conteneurs et infrastructures
l. Littéralement un «ch amp vert » qui symbolise l'absence d'existant, aussi appelé legacy.
2.3 Ansible, Chef et Puppet: obiet et lien avec Docker et CaaS _ _ _ _ _ _ _ _ _ _ _ _ _ _ EJ
Ces solutions se basent sur des DSL 1 (Domain Specific Language ) qui permettent de
déclarer la configuration cible à atteindre pour des systèmes éventuellement distribués.
Cette configuration peut recouvrir :
• la configuration de l'OS ;
• l'installation et la configuration de logiciels standards ou personnalisés;
• la gestion de services (démarrage, redémarrage);
• l'exécution de commandes distantes.
Le but de ces outils est de remplacer les nombreux scripts (shell, python, perl, etc.)
couramment utilisés pour les tâches courantes de configuration et de déplo iement par
une bibliothèque d'actions standardisée utilisant un seul langage, une seule solution.
,- ..\
Fichier 'r'
1/ I
JSON / YAML
Orchestrateur et Il I
,,,
1 I
configurateur
Commandes de
configuration native pour
le host ciblé
Contrairement à d'autres solutions, Ansible est une solution dite agentless. Cela
signifie qu'il n'impose pas l'installation d'un agent sur l'hôte qui doit être configuré.
La seule exigence est de disposer d'un accès SSH et que Python (2.x) soit installé
sur cette machine distante.
La notion d'inventaire
Une fois Ansible installé sur la machine de contrôle (celle qui va configurer les autres),
une lign e de commande va permettre de prendre le contrôle des h ôtes ciblés. Ces h ôtes
cibles sont organisés dans ce qu'Ansible nomme un inventory. Celui~ci, par défaut, se
trouve dans le fichier /etc/ansible/hosts dont voici un exemple :
[ frori leri d ]
feül .examp l e . com
fe02 .example . com
fe03 .[Link]
[backend]
beül .example . com
be02. exampl e . com
l:l
0
c Ces machines (qui peuvent être virtuelles grâce à des connecteurs pour diverses
:::i
0 solutions cloud comme AWS) sont organisées en groupes. Ces groupes vont permettre
\.0
.-t de lancer des actions de masse. On peut vouloir, par exemple, mettre à jour tous les
0
N serveurs web ou bien faire un ping sur toutes les machines de l'inventaire, comme
@
.......
ci~dessous :
..c
O'l
'i:
>-
0. $ ansi bl e al l ·m ping
0
u feü l .example . com 1 SUCCESS => {
"changed" : f al se ,
"pin g" : "pong "
}
fe02 . examp l e . com 1 SUCCESS => {
"changed ": fa l se .
"pin g" : "pong"
)
2.3 Ansible, Chef et Puppet: obiet et lien avec Docker et CaaS _ _ _ _ _ _ _ _ _ _ _ _ _ EJ
Dans le cas ci,dessus le a 11 signifie « toutes les machines de l'inventaire » qui,
dans ce cas, n'est constitué que d'un seul et unique hôte. Si l'inventaire correspondait
à l'exemple de fichier /etc/ansible/hosts listé plus h aut, alors la commande suivante
serait aussi valide :
Un exemple de playbook
Un playbook Ansible va décrire l'état cible souhaité pour un ou plusieurs hôtes.
L'exemple ci,dessous (stocké dans un fichie r install_apache.yml) v ise à installer le
serveur web apache :
- hosts : al l
user : ma f
become : yes
become_user : root
tasks :
- name : in sta l l er l a derni ère version d' apache
yum : name=htt pd st ate=la test
- name : con f i gurer apac he pour se lan cer au démarrage du système
service : name=httpd state=started enabled=yes
Nous n'entrerons pas dans le détail de l'usage d'Ansible, mais sachez que le fichier
ci-dessous suppose un certain nombre de choses concernant l'hôte cible. Nous voyons
notamment qu'un utilisateur « maf » doit exister sur cet hôte et que celui-ci doit être
l:J pourvu des droits sudo, afin de pouvoir fonctionner en mode root. Il est aussi nécessaire
0
c
::J
~
.
., d'avoir fait un échange de clefs SSH entre le contrôleur et l'hôte à configurer.
"O
0 c::;
\.0
.-t
0
.,.,
~
Ansible va se connecter à l'hôte (via SSH) et :
N
·~
@ ·c • vérifier qu'Apache est bien installé et qu'il s'agit de la dernière version dispo,
....... B::;
..c: CO nible ;
Ol c
ï:::: 0
>- c • que celui,ci est bien installé pour démarrer au boot de l'hôte.
o.. c
u
0 ·3
<.)
::;
"O
0
..... Une description, pas un script impératif
c.
~
~
::;
Il est important de comprendre que le descripteur ci,dessus n'est pas une séquence de
rS commandes impératives. Il s'agit de la description d'un état souhaité pour l'hôte.
1
"O
0
c Lançons la commande une première fois sur un h ôte sur lequel Apache n'est pas
8 installé :
(Ç)
Chapitre 2. Conteneurs et infrastructures
PLAY RECAP
*********************************************************************
10 .0. 2.4 : ok=3 changed=2 unreac hab l e=O f ailed=O
La séquence se conclut par le message changed 2 qui fait référence aux deux
actions opérées par Ansible :
• installer Apache avec sa dernière version ;
• faire en sorte qu'il démarre au boot de la machine.
PLAY
***************************************************************************
Comme nous l'avons vu, Ansible présente une similarité conceptuelle avec les CaaS.
Le système fonctionne en comparant un état actuel avec l'état cible.
l:J
0 Chef ou Puppet fonctionnent selon le même principe, si ce n'est qu'à la différence
c ~
.
.,
::J
"O d'Ansible, ceux-ci requièrent l'installation d'un agent sur l'hôte.
0 c::;
\.0
.-t
0
.,.,
~
hasts : all
user : ma f
tasks :
name : fait en sorte qu' un cont ene ur web t ourne su r l a machine cibl e
docker :
name : myserver
ima ge: ng i nx
sta t e: started
ports: 8080 :80
"'Cl
En résumé
0
c Dans ce chapitre, nous avons vu la manière dont les conteneurs, et plus spécifique-
:::i
0
\.0
ment Docker, étaient en train de coloniser les solutions de gestion d'infrastructures.
.-t
0 Nous avons étudié les solutions CaaS dédiées aux architectures applicatives exclu-
N
sivement à base de conteneur. Nous nous sommes aussi attardés sur les solutions de
@
....... gestion de configuration, comme Ansible, Puppet ou Chef qui s'intègrent aussi à
..c
O'l
'i:
Docker ou des solutions CaaS, comme Kubemetes.
>-
0.
0
u
Docker en pratique ••
les outils de base
Cette seconde partie constitue une prise en main de Docker et des outils de base de
son écosystème.
Le premier chapitre décrit l'installation des outils Docker e t de l'environnement
qui sera ensuite utilisé pour les d ifférents exemples pratiques de cet ouvrage. Ce
chapitre nous perme t aussi d'aborder les bases du fonctionnement du démon et du
client Docker.
l:J
Le deuxième chapitre est consacré spécifiquement à deux exemples significatifs
0
c ~
.
., d'installation et de configuration d'hôtes Docker. Nous y abordons aussi des questions
::J
0 "O
c::; relatives à la configuration du stockage Docker pour les OS de type Fedora.
\.0
.-t
0
.,.,
~
Le dernier chapitre aborde la création et le cycle de vie des conteneurs au travers
N
·~ d'un exemple pratique. À ce titre, nous verrons pour la première fois quelques exemples
@ ·c
B
.......
..c:
::;
CO
de commandes Docker.
Ol c
ï:::: 0
>- c
o.. c
u
0 ·3
<.)
::;
"O
0
.....
c.
~
~
::;
rS
1
"O
0
c
8
(Ç)
"'O
0
c:
:::i
0
\.0
r-1
0
N
@
......,
..c:
en
·;::
>-
0..
0
u
3
Prise en main
l:J
0 3.1 INSTALLATION DE DOCKER
c
::J
~
,.,
"O
0 c::;
\.0 L'installation de Docker est en général simple et rapide à effectuer sur une distribution
.-t
0
.,.,
~
N Linux. On peut bien sûr aussi l'utiliser à travers un environnement virtualisé sous
'~
@ ·c
B
Windows et Mac OS X, Prochainement, grâce aux implémentations natives en
....... ::;
..c: CO préparation (s'appuyant sur une VM xhyve sous Mac OS X et Hyper~V sous Windows),
Ol c
0
ï::::
>- c il sera aussi possible d'installer Docker directement sous Windows ou Mac OS X.
o.. c
u
0 ·3
<.)
::;
"O
0
.....
~
c. 3.1 .1 Docker Toolbox : la solution rapide pour Windows et Mac OS X
~
::;
rS Le plus simple pour démarrer rapidement et efficacement Docker sous Windows ou
1
"O
0
Mac OS X est d'utiliser Docker ToolBox. C e dernier est un programme d'installation
c
8 élaboré par Docker lnc., qui contient tous les logiciels nécessaires pour l'utilisation de
(Ç) Docker sur un environnement autre que Linux :
El-------------------------- Chapitre 3. Prise en main
Docker ToolBox utilise Docker Machine pour créer une machine virtuelle (VM)
Linux minimale tournant sous Windows ou Mac OS X, grâce à VirtualBox. Cette
VM fait tourner le démon Docker qui peut ensuite être contrôlé depuis votre système
d 'explo itatio n de différentes façons :
• via Kitematic ;
• via le client Docker ;
• en direct grâce à des requêtes HTTP (n'oublions pas que le démon Docker
expose son API en REST2 ).
Pour pouvoir installer Docker Toolbox, votre machine doit disposer de Windows 7 ou
supérieur, ou Mac OS X 10.8 ou supérieur.
L'utilisation de Docker Toolbox, bien que pratique, a néanmo ins ses limites dès
que l'on commence à utiliser les data volumes car la machine virtuelle et la machine
h ôte n e p;:irn:igent p;:is le même système de fi chiers. H eureusement, il existe une
autre méthode, utilisant les capacités de partage de fichiers entre hôte et invité de
VirtualBox (nommée shared folders), qui permet de s'affran chir de ces problèmes, mais
au prix de performan ces relativement médiocres.
V VAGRANT """"... ..
l:J
0
c $ vagrant i nit dunod -docker/centos7
:i
0 A 'Vagran tfi l e' has been pl aced in this di recto ry . You are now
\.0
.-t ready t o · vagrant up· your f i rs t vi rtua l env i ronment ! Pl ease read
0
N t he comments i n t he Vagrantf il e as wel l as documentation on
@ 'vagrant [Link]' for more information on using Vagrant .
.......
..c
en Vagrant va télécharger la box et ensuite créer une machine virtuelle automatique-
·c
>-
0. ment.
0
u
1. [Link] [Link]/dunod-docker/boxes/centos 7
2. [Link] (version utilisée dans ce livre 5.1.14)
3. [Link] (version utilisée dans ce livre l. 7.4)
3. 1 Installation de Docker ---------------------------8
$ vagrant up -- provider vi rtualbox
Bringing machine 'defa ult ' up wi t h 'vi rt ualbox ' prov ider .. .
==> default : Importi ng base box ' dunod -docker /centos7' .. .
==> default : Matching MAC address for NAT networking .. .
==> default : Checking i f box ' dunod -docker/centos7 ' is up
to date ...
==> defau l t : Setting t he name of the VM : VM_defau l t 1462554217727_87155
==> default : Clearing any previously set networ k interfaces ...
==> defau l t : Preparing networ k i nterfaces based on con fi gurat ion . ..
defau l t : Adapter 1: nat
==> default : Forwarding ports ...
default : 22 => 2222 (adapter 1)
==> default : Booting VM ...
==> defau l t : Wa i ting for machine to boat . This may take a few minutes ...
defau l t : SSH address : 127 .0.0. 1:2222
default : SSH username : vagrant
defau l t : SSH auth method : private key
default : Warning : Connect i on ti meout. Retry i ng .. .
default : Warning : Remote connection disc onnect. Ret rying ...
default :
default : Vagrant i nsecure key detected . Vagra nt wi l l automatica l ly replace
defaul t : th i s wi t h a newly generated keypa i r for better security .
default :
default : Inserti ng generated public key with i n guest ...
default : Removing i nsecure key fr om the guest if it 's present . . .
def aul t : Key i nserted! Di sconnecti ng and reconnecting us i ng new SSH key ...
==> def ault : Machine booted and ready !
==> def au l t : Chec ki ng f or guest additions i n VM . . .
==> def au l t : Mounti ng shared fo l ders ...
default : /vagrant => C: /Users/dunod/Document s /VM
u
0 ·3
<.)
::; Oublier l'etat sauvegarde... Ctrl+J
"O
0 ~ Afficher le journal... [Link]+l
.....
c. l:!J Actualiser
~
~
ITII Afficher dans l'explorat,ur de fichittS \
::; ~ Créer un raccourci sur le bureau
rS ,._===-=' Ri! Trier
1
"O
0
c
8 Figure 3.3 - Accès à l'image Vagrant pour se connecter
(Ç)
El------------------------- Chapitre 3. Prise en main
Vous pouvez ensuite vous connecter sur cette machine virtuelle avec l'utilisateur
vagrant (mot de passe vagrant).
l/J Réseau
El lecture ..U.
0 Montage ..,tcmatique
~ Portss~ries
1 OK 11 ..........
~
1
Dossiers partagés
~ Interface utilisateur
OK J [ "'1ntJer J [ Aide
Au démarrage de votre VM, un lien sera créé entre le répertoire dans lequel vous
avez lancé la commande vag r ant up et le chemin /media/sf_vagrant dans votre VM.
l:J
0
c
::J
~
,.,
0 "O
c::;
Attention cependant, depuis l'intérieur de la VM, le chemin /media/sf_vagrant ne
\.0 sera accessible qu'à partir de l'utilisateur root ou d'un utilisateur disposant des droits
.-t
0
.,.,
~
N
'~
sudo, ce qui est le cas de notre utilisateur vagrant .
@ ·c
....... B::;
..c: CO
Ol
0
c Maintenant que nous disposons d'une machine virtuelle Linux, il ne nous reste
ï:::: c
>- c plus qu'à installer le Docker Engine.
o..
u
0 ·3
<.)
::;
"O
0
.....
c.
Installation de Docker dans notre VM
~
~ Docker est disponible via les différents gestionnaires de packages des distributions
::;
rS Linux (aptitude pour Ubuntu/Debian, yum pour RedHat/CentOS, dnf pour Fedora)
1
"O
0
c Pour obtenir la dernière version de Docker, il est généralement conseillé d'utiliser
8 le dépôt de packages proposé par Docker.
(Ç)
El------------------------- Chapitre 3. Prise en main
La distribution Linux sur laquelle vous voulez installer Docker do it remplir les
prérequis suivants pour être prise en charge :
• une architecture 64 bits, Docker n'étant pas supporté en 32 bits;
• un kemel Linux récent (au moins en version 3.1 0), même s'il est possible de
trouver des versions depuis la version 2.6 sur lesquelles Docker fonctionne.
1 $ sudo su
• rajoutez le dépôt docker pour yum (cela permet d'obtenir la dernière version de
docker, étant donné que le dépôt central CentOS met du temps à être mis à
jour) :
Vous pouvez maintenant vérifier que tout fon ctionne correctement grâce au
conteneur de test hello,wo rld :
$ docker ru n he l l o-world
Unabl e to find ima ge ' hello -world : l atest ' l oca ll y
l at es t : Pull ing from library/ hel lo -wor l d b90l d36b6f2f :
Pu l l compl et e Oa6 ba66e537a:
Pu 11 comp l et e
Diges t : sha256 :8be990ef2aeb16dbcb92 71 ddfe2610fa6658d l 3f6df b8bc72074cc l ca36966a 7
St atus : Downl oaded newer i mage for hel lo -wor l d: latest
Hel l o from Docker. Thi s message shows t hat you r i ns t al l ati on appears t o be
working correctl y.
Finaleme nt, pour éviter de devoir préfixer toutes les commandes Docker par un
sudo , il est possible de créer un groupe docker et d'y rajouter votre utilisateur (dans
notre cas, vagrant) :
3.2.1 Kitematic
Kitematic est un logiciel fourni avec Docker ToolBox (donc disponible uniquement
sous Windows et Mac OS X) qui permet de gérer les conteneurs d'un démon Docker
local. Il permet d'appréhender Docker visuellement sans utiliser la ligne de commande.
Pour utiliser Kitematic, vous devez avoir un compte sur le Docker Hub 1 . Il n'y a pas
à proprement parler de raison technique à cette obligation. Il s'agit pour la société
Docker lnc. de promouvoir son Hub qui joue un rôle essentiel dans lécosystème
Docker.
• •• @-·
Containers AU Reoommencled My Repos
-
Recommended
h8'1o--world·nginx
A lghl·wtlQhl nQIRlt oontliMt
tt'll~•ths,....._of
ghost
_
..
Ghoet . . . fJM and open 80WCI
...
blogg~ [Link] .mtten ln
""'"
redîs
..
rethinkdb
-~
minecraft
Red!• .. .,, open IMJUIÇ9 . , . . Reit*lkOBlaen~. The Mlneçrsft [Link] M'Wlf"
va.. ltor9 ttm blction• - • document cMtmu. tlwl ""*- il lllowstwoormoM~to
911SYtO bulkl and ICate ruàlml•.• play Minecratt togethef'
l:J
L J ~ L
-
0 c;:;i 1487 000 CREATE \) 151
-
34 000 CHA1T 1
c
:i
0 s oir e tasticsearch -postgres !
\.0 Sc*' .. the [Link]. blal;lng-1-t,
.-t open IOU'Ce entetptlu MIM:l't
pladonn blAt on Apache,_.
0
N
@
~ 65 000 CAERt.J
.......
..c
en
'i:
>-
0.
Il =
.
tu-upstart
. .......
Upàmt ls an -"'..baed
Pour prendre en main Kitematic, cliquez sur le bouton Create de l'image hello~
world~nginx. Kitematic va alors télécharger l'image correspondante depuis le Docker
Hub, puis créer et démarrer un conteneur à partir de cette image.
l. [Link]
3.2 Votre premier conteneur --------------------------[!!]
• e• @ tu-tot v heHo-world-nginx ~
Containers
Home Setttngs
WEBPREV1EW 1~ I@
® en©
Voitàl Your nginx container i:s runningt
VOLUMES
/webslte_files
Kitematic liste tous les conteneurs existants arrêtés ou actifs (ce qui est indiqué
par la marque « A » sur la figure 3.8). O n voit dans notre cas le conteneur que nous
venons de créer.
Kitematic assigne comme nom par défaut le nom de l'image. S'il y en a plusieurs,
elles sont suffixées par _ 1, _2 ...
N ous en avons terminé avec cette introduction rapide à Kitematic et vous trouverez
des informations complémen taires dans le guide d'utilisateur de Docker 1•
Nous allons maintenant étudier l'utilisation du client Docker en ligne de com-
mande, qui reste la méthode principale d'interaction avec le démon Docker, du moins
dans un cadre p rofessionnel.
Vous avez déjà utilisé le client Docker, peut-être sans le savoir, durant la phase
d 'installation, lorsque vous avez saisi la commande docker r un he l l o-wor l d.
Avant d'aller plus lo in dans l'explication de son utilisation , il est temps de regarder
un pe u plus en détail comment le démon Docker interagit avec le reste du monde.
Le démon Docker écoute sur un socket U nix 2 à l'adresse /var/run/[Link]. Le
clien t Docker utilise HTTP pour envoyer des commandes à ce socket qui sont ensuite
transmises au démon , aussi v ia HTTP.
localhost
HTTP HTTP
l:J Socat est une boîte à outils qui permet de spécifier deux flux de données (des fichiers,
0
c
:i
des connexions .. .> et de transférer les données de l'un vers l'autre.
0
\.0
.-t La figure ci-contre permet de comprendre ce que nous allons faire. Nous insérons
0
N un socket proxy, qui va d'une part transférer les commandes du client au démon Docke r,
@ et d 'autre part, les afficher dans notre fenêtre de terminal.
.......
..c
en Installez socat à l'aide du gestionnaire de paquet yum:
'i:
>-
0.
0
u 1 $ sudo yum in sta ll -y socat
1. [Link] ic/userguide/
2. h ttps://fr. wikiped [Link]/wiki/Berkeley_sockets#Socket_un ix
3. h ttp://[Link]-unreach .org/socat/
3.2 Votre premier conteneur ------------------------8
localhost
Client docker
HTTP
/tmp/[Link] 1 /var/run/[Link] ~
HTTP
S_ GET 'V1 21
Démon docker
Le groupe docker
Souvenez-vous, lors de l'installation de Docker, nous avions rajouté notre utilisateur
vogront dans un groupe docker.
Le client et le démon Docker ont besoin de tourner avec des droits de type root
(cela est nécessaire pour pouvoir, par exemple, monter des volumes). Si un groupe
docker existe, Docker va donner les permissions sur le socket /var/run/[Link] à
ce groupe. Tout utilisateur en faisant partie pourra donc ensuite utiliser Docker sans la
commande sudo.
"'Cl
0
3.2.3 API Docker Remote
c
:::i
0 Le démon Docker expose l'intégralité de ses méthodes à travers l'API Docker Remote 1 •
\.0
.-t C'est une API de type REST qu'il est possible d'appeler avec des outils tels que curl
0
N ou wget, à partir du moment où la configuration le permet.
@
.......
..c
O'l Docker info avec curl
'i:
>-
0.
0 Rappelons que Docker n 'écoute que sur un socket Unix à l'adresse
u /var/run/[Link], comme nous l'avons vu précédemment. Pour pouvoir appeler
l'API directement avec un client HTTP, il faut que nous définissions un autre socket
de connexion de type TCP.
Pour cela, arrêtons le démo n :
Pour se connecter à notre démon, il faut maintenant passer l'adresse que nous
venons de définir avec le paramètre - H :
1 2 7 .0.0.1 vs o.o.o.o
Nous sommes tous plus ou moins familiers avec l'IP [Link] : c'est l'adresse IP de
loopback, aussi connue sous le nom de localhost. Cette adresse est associée à une
interface réseau virtuelle qui ne permet de communiquer qu'avec l'hôte lui-même (elle
n'a donc de sens que pour les processus tournant sur cet hôte et n'est pas accessible
depuis l'extérieur).
L'adresse [Link] est une autre adresse standard. Elle signifie« toutes les adresses 1Pv4
de la machine » (incluant donc 1 2 [Link], d'où le message d'alerte faisant référence
au loopback qui s'est affiché lorsque nous avons démarré le démon). Le démon ainsi
associé à l'adresse 0 .0.0.0 est donc accessible depuis n'importe quelle adresse <ce qui
n'est généralement pas le cas dans un environnement sécurisé de production).
"'Cl Si nous ne voulons pas avoir à spécifier à chaque appel le paramètre - H, il suffit
0
c
:::i
de définir la variable d'environnement DOCKER_HOST et ainsi le client Docker
0 l'utilisera automatiquement :
\.0
.-t
0
N
@ 1 $ export DOCKER_HOST="tcp: //0 .0.0.0:2375 "
.......
..c
O'l
'i:
Utilisons maintenant curl pour appeler directement le démon Docker. Pour rendre
>-
0. la réponse ]SON plus lisible, nous allons employer jq 1 , et il faut donc installer le
0
u paquet nécessaire :
nécessaire de modifier l'instruction de démarrage par défaut du démon Docker via les
instructions suivantes:
En résumé
Dans ce chapitre nous avons appris à installer Docker sur une machine de bureau.
Nous avons appris à interagir avec le démon Docker au travers de divers outils pour
lancer des commandes et créer des con teneurs. Dans notre prochain chapitre, nous
allons nous intéresser à l'installation de Docker sur un hôte serveur de manière plus
professionnelle.
"'Cl
0
c
:::i
0
\.0
.-t
0
N
@
.......
..c
O'l
'i:
>-
0.
0
u
1. h ttps://[Link]/engine/ad mi n/systemd
4
Docker sur un serveur
Avant tout, Docker Machine requiert que le Docker Engine soit installé sur votre ordi-
nateur. Docker Machine est l'un des composants de la Docker Toolbox. Vous pouvez
vous reporter au ch apitre précédent pour plus de déta ils con cernant l'installation de
cette boîte à outils.
Il est aussi possible de télécharger le bina ire de Docker Machine manuellement et
de l'extraire en adaptant les permissions pour le rendre exécutable :
Nous avons installé ici la dernière version disponible de Docker Machine <0.6.Q)
au moment de l'écriture de ce livre. Vérifiez et utilisez toujours la dernière version
"'Cl
0 disponible en mettant à jour l'URL d'installation dans les commandes ci-dessus.
c
:::i
0
\.0
Vérifion s fina lement que l'installation s'est bien déroulée en affichant la version
.-t
0 de Docker Machine :
N
@
.......
..c $ docker -machi ne version
O'l
ï:::::
>-
1 docker -mach i ne version 0.6.0, build e27fb87
0.
0
u Explorons maintenant les capacités de Docker Machine pour bien comprendre son
fonctionnement.
Il faut vraiment voir Docker Machine comme un outil de pilotage distant d'hôtes avec
Docker, que ce soit en local, dans votre cloud d'entreprise ou sur un fournisseur cloud
(comme Amazon AWS ou Microsoft Azure).
Amazon EC2
Window5Azure-
vmware-
..
openstack
, ,
Docker Machine repose pour cela sur un mécanisme de drivers. Chaque driver est
spécifique d'un type d'installation et vous permet de créer une machine Docker pour
un environnement spécifique.
l:J
0
c ~
,., Dans la suite de ce chapitre, nous utiliserons de manière interchangeable le terme
:i
0 "1:l
c;:;
machine et hôte, une machine n'étant finalement qu'un hôte sur lequel tourne un
\.0 démon Docker.
.-t ~
0 V
N V
'&
@ ·c On peut catégoriser ces drivers de la manière suivante:
....... B
;:;
..c CO
• ceux qui permettent de créer une machine localement sur votre poste de travail.
en c
0
ï::::: c
>- c
Dans ce cas, Docker Machine interagit directement avec le programme de
o.
u
0 ·3
<.)
virtualisation, tel qu'Oracle VirtualBox, M icrosoft Hyper-V ou VMware Fusion ;
;:;
"1:l
0
..... • ceux qui gèrent des machines sur une infrastructure privée d'entreprise :
c.
~ OpenStack ou VMware vSphere par exemple;
2:l;:;
rS • et ceux qui utilisent des infrastructures cloud, telles que Digital Ocean, G oogle
1
"1:l
Co mpute Engine ou Microsoft Azure.
0
c
8
(Ç) 1. h ttps://gi thu [Link]/docker/mach ine/tree/master/con trib/completion/bash
El----------------------- Chapitre 4. Docker sur un se1Veur
La liste des d rivers officiellement supportés par Docker Mac hine évoluant régu-
lièrement, il est plus simple de se référer au site de Docker pour disposer de la liste
exhaustive. L'a rchitecture modulaire de Docker Machine a aussi permis à des tierces
parties de créer des drivers supplémentaires (tel KVM 1 ) dont la liste se trouve sur le
dépôt GitHub de Docker Machine2 .
Regardons maintenant plus en détail la commande doc ker- machine creat e.
Comme son nom l'indique, la commande docker -mac hi ne create permet de créer
des machines avec un Docker Engine et de configurer directement ce de rnier. Elle
nécessite pour cela au mo ins deux paramètres :
• - -dri ver : comme nous l'avons vu précédemment, c'est le nom du driver qui
sera utilisé, par exemple virtualbox ou digitalocean ;
• le nom de la machine, à donner généralement en fin de commande.
Il y a bien sûr de nombreux autres paramètres que l'on peut lister avec la commande
suivante :
De plus, pour obtenir de l'aide sur un driver particulier, il suffit de rajouter son
nom, par exemple, pour le driver Virtualbox :
Docker Machine utilise pour certains de ces paramètres des valeurs par défaut. Par
exemple, si vous créez une machine sur le cloud Microsoft Azure, la valeur par défaut
du paramètre azure -si ze, qui définit la taille de la machine, est Smalt.
1. [Link]
2. [Link] r/mach ine/blob/master/docs/AVAILA BLE_DRIVER_PLUGINS.md
4. 1 Docker Machine
Nous en savons maintenant assez pour créer nos premières machines. Commençons
par une machine sur le cloud d' Amazon AWS.
Avant tout, il faut évidemment que vous disposiez d\m compte Amazon AWS.
S i ce n'est pas le cas, rendez~vous sur [Link] pour en créer un.
Vous disposez automatiquement de l'offre AWS Free Tier qui inclut une machine
virtuelle avec un abonnement [Link] pour une durée d'un an qui vous permettra
d'expérimenter Docker Machine.
Attention, l'offre AWS Free Tiers n'inclut pas une adresse IP statique pour la machine
virtuelle, ce qui signifie que l'adresse IP va changer et que les certificats TLS générés
par Docker Machine pour sécuriser le Docker Engine ne seront plus valables. La
solution est d'activer une Elastic IP qui permet ainsi d'obtenir une adresse IP statique,
mais il vous en coûtera un peu d'argent.
Pour obtenir ces deux valeurs, il faut se connecter à la console Amazon AWS.
Les prérequis
Nous allons tout d'abord créer un groupe avec des droits d'administration, puis un
utilisateur de ce groupe. Finalement, nous créerons pour cet utilisateur les clés d'accès
"'Cl
0
requises par Docker Machine.
c
:::i
0
.-. AWS v Services v
\.0
.-t
0
N
Dashboard
+•§§i#ir!i!i GroupActions •
@ Search IAM
....... Rlter
..c Details
O'l
'i: 1 Groups
0 Group Name ; u..,,.
>-
0.
0 Users 0 docker-machine O
u Rotes
Policies
ldentity Providers
Accounl Settings
Credenlial Report
Encryption Keys
Poticles
Acoount Settings This Vlew shows aJI groops the User bekmgs to: 1 Group
Crlldenlial Report
Group
Il ne nous reste plus qu'à définir un mot de passe pour notre utilisateur :
• allez dans l'onglet Security Credentials et cliquez sur Manage Password;
• choisissez Assign a custom password, saisissez un mot de passe deux fois et
confirmez.
4. 1 Docker Machine
Via la console AWS, nous pouvons voir qu'une n ouvelle machine virtuelle a bien
été créée:
.-. AWS - Servicoa "' Thomas [Link]!ot v ~ Vrq no;)• SJPOOrt •
4
Fi %%J1 if f. f Connoct Actionl v
Spot Requests
Reserwd Instances
l:J Scheduted lnstvices
0
c
::J
~
,.,
"O [Link]:« ll-t211b01e ([Link]) P\lblic; ONS: oc:2~-[Link]-1 ..[Link] !!ll!lc:I
0 c::;
\.0 Onc;riptlon stBtUS CMclcs Monitoring Tags
.-t
0
.,.,
~
- 6..ASTIC BLOCK STORE ec2-52-23-201-101 .~1..-[Link]
'~
..
[Link])'p9 [Link]
@ ·c [Link] lp-172-31-10-7 1. .::[Link]â
....... B::;
........, SecuritJ' 91"1M4>• dcx:ks-nw::hne. Ylawn-..
..c: CO
Bastlc!PI
[Link]• NQ~~
Ol c ubuntu-wlloj-15.1G-amd&4-181'Ver-20151118. 1 {9ml-2&05at4q
ï:::: 0
c KeyPaira
.....
........
~
>- c
Networkimlr'fM:. . eltlO
o.. Source/dut.. [Link] True
u
0 ·3
<.) EBS-optimldd Felse Laincti time Mllrcf1 1, 2018 at 1Ck2721 NJ. l1TC• 1 ~thaionehOll')
::;
"O
0
.....
c.
~ Figure 4 .4 - Machine virtuelle EC2 provisionnée par Docker Machine
~
::;
rS
1 Détaillon s un peu ce qui s'est passé :
"O
0
c
8 • Docker Machine s'est connecté à l'interface d'Amazon EC2 et a lancé la
(Ç) création d'une machine v irtuelle avec le nom aws-machine ;
El----------------------- Chapitre 4. Docker sur un se1Veur
• cette machine est localisée par défaut dans la région géographique us-east-1 que
nous aurions pu modifier, via le paramètre amazo nec 2- reg i on;
• cette machine est basée sur l'AMI (modèle de machine virtuelle Amazon) ami-
26d5af4c qui repose sur une Ubuntu 15.10. De nouveau, il s'agit d'une valeur
par défaut que nous aurions pu surch arger avec le paramètre amazon ec2 - ami en
utilisant, par exemple, une AMI personnalisée.
Si vous désirez en savoir plus, la liste des valeurs par défaut est disponible sur la page
de documentation du driver Amazon de Docker Machine1 .
l
N"tann:: 14211b011 (aws-mad11rwj Putllic DNS: K.2-5.2·23-164·[Link].-.com l!!!!l!!I
[Link] [Link]
Prl't• DHS lp-172-31-10-71.-:[Link]
Pl'MlttolP9 172.31 .10.71
l:J
0
Figure 4.5 - Ports ouverts par Docker Machine
c
:i
0
\.0
.-t
0 Pour sécuriser la connexion SSH, Docker Machine génère une clé RSA. La partie
N
@ publique de la clé est ensuite copiée sur notre machine virtuelle (on la retrouve
.......
..c d'ailleurs via la console AWS sous le menu N etwork & Security, puis Key Pairs) .
en
ï:::::
>-
0.
0
Données de configuration locales
u
Lorsque vous utilisez Docke r Machine depuis un hôte, un certain nombre de fichiers
de configuration sont créés e t conservés.
Par exemple, dans le cas de notre machine EC2 :
l. [Link] ine/drivers/aws/
4.1 Docker Machine ---------------------------8
$cd -/ .docker/machine/machines/aws -mach i ne/
[aws-mach i ne ]$ l s -1
ca . pem
cert . pem
con fig .json
i d_rsa
id_rsa . pub
key . pem
server-key . pem
server . pem
O n retrouve :
• n otre clé SSH (id_ rsa et id_ [Link]) ;
• un [Link] [Link] qui contient les détails de la configuration de notre
machine ;
• et un ensemble de certificats.
Ces certificats sont utilisés pour sécuriser l'accès à l'interface HTTP du démon
Docker à l'aide de TLS, ce qui sera expliqué en détails dans le chapitre 8 sur la
sécurisation du démon Docker.
N
'~
@ ·c
.......
..c:
B::;
CO
4.1.5 Installation de Docker avec Docker Machine et Oracle VirtualBox
Ol c
ï:::: 0
c
>-
o.. c La création d'une machine sur VirtualBox nécessite évidemment que VirtualBox soit
u
0 ·3
<.) installé sur votre poste de travail. C'est le cas si vous utilisez Docker ToolBox présenté
::;
"O
0
..... dans le chapitre précédent.
c.
~
~ Le processus de création est très similaire à celui que n ous venons de suivre pour
::;
rS A mazon AWS: c'est d'ailleurs là un point fort de Docker Machine. Le principe des
1
"O
0
drivers permet de masquer simplement l'hétérogénéité des processus d 'installation.
c
8 Créons donc n otre machine local~machine avec le driver v irtualbox :
(Ç)
Chapitre 4. Docker sur un se1Veur
Docker Machine se base ici sur une image [Link], et non pas sur une
image Ubuntu, comme pour Amazon AWS. Cette image est copiée dans le répertoire
-/.docker/cache pour accélérer la création ultérieure d'autres machines locales. Elle est
ensuite copiée dans le répertoire de notre machine -/.docker/machine/machines/local~
machine.
À nouveau, Docker Machine utilise un ensemble de valeurs par défaut pour créer
"'Cl
0 notre machine, chacune pouvant être surchargée 1• Le reste du processus de création
c
:::i est identique à celui de notre machine Amazon EC2 :
0
\.0
.-t • génération d'une clé RSA pour nous connecter en SSH ;
0
N • copie des certificats nécessaires pour sécuriser avec TLS le démon Docker ;
@
....... • configuration du démon Docker avec des valeurs par défaut.
..c
O'l
'i:
>-
0.
0 4.1.6 Quelques autres commandes utiles
u
Nous pouvons lister toutes les machines administrables depuis le poste de travail
avec la commande docker-mac hi ne l s (l'utilisation du paramètre optionnel - -format
permet de personnaliser le détail des informations que nous voulons visualiser, dans
notre cas le nom de la machine, son driver, son URL et la version de Docker2 ) :
1. [Link]
2. [Link] ne/reference/ls/
4.1 Docker Machine ---------------------------[!!]
$docker -machine l s -- format "{{ . Name}} : {l. DriverName}} - {{. URL }} -
{( . DockerVersion}} "
aws-mach i ne : amazonec2 - tcp : //52 . 23 . 164 . 218:2376 - vl .1 0. 2
1 local -machine : virt ualbox - tc p: //192 . 168 .99 .1 01 :2376 - vl . 10 . 2
Utilisons maintenant notre machine pour démarrer un conteneur. Pour cela, nous
devons avant tout définir un certain nombre de variables d'environnement pour
indiquer à notre client Docker sur quelle machine il doit se connecter. Nous disposons
l:J
0 pour cela de la co mmande suivante :
c
::J
0
\.0
.-t $docker -machine env local -machine
0
N
export DOCKER_TLS_VER IFY= "l "
@ export DOCKE R_HOST="t cp : // 192 .1 68 .99 .1 01: 2376 "
....... export DOCKE R_CE RT_PATH=" / Users/ t homas / .docker/mac hin e/mach i nes / l ocal -machine "
..c:
O'l expo r t DOCKER_MACHI NE_NAME= "loca l -machine "
·;::
>- # Run t his command t o conf i gure yo ur shell :
0..
0 # eva l $(docker-mach i ne env loca l -mach i ne)
u
Pour configurer votre environnement avec ces variables, utilisez la commande
proposée et vérifiez ensuite avec la commande docker-mach i ne active que notre
machine local-machine est bien celle qui sera utilisée par la suite.
Par défaut, la commande doc ker-mach in e env génère un résultat pour un terminal
Unix de type bash. Si vous utilisez Windows (Powershell ou cmd), il vous suffit
de rajouter le paramètre - - she 11 pour obtenir un résultat compatible avec votre
environne ment. Par exemple, pour Powershell :
$ docker -machi ne. exe env --s he ll powers hell loc al- machine
$Env:DOC KER_TLS_VE RIFY = "l "
$Env:DOCKER_HOST = "tcp : // 192 . 168 . 99 .101: 2376 " $Env :DOC KER_C ERT_PATH
"C: \Users\thomas\ .doc ker\machine\mach i nes\local -machine "
$Env:DOCKER_MACH INE_NAME = " loca l -mach i ne "
If Run t hi s comma nd to configure your shel l :
If docker -machine .exe env -- shel l=powers hel l local -machine Invoke - Express ion
1
Toutes les comma ndes de notre clie nt Docker utiliseront désormais le démon
Docker tournant sur notre machine local~machine.
Démarrons notre premier conteneur :
N ous pouvons même nous connecter en SSH pour vérifier que notre conteneur a
l:J
0
bien été créé sur cette machine :
c
::J
0
\.0
.-t
$ doc ker -machine ssh l oca l -machine
0
N
1111
@ IfIf ffff IfIf
....... fl1f ff ff ffff ffff ffff
..c: ; 11 11 11111111111111111111 1111111111 \ / ===
O'l
ï::::
>- (-- ---- --- ---- --- - /
0.. \ 0 /
0
u \ \ /
\ \ /
- -
1- - 1 1-1- \ -1 1 -1 1 - --
_ \ I _ \ I _ \ I - 1 _ l I _ · JI _ \ I -1 Il I _ \ '-1
1- l 1 (_) 1 (_) 1 1- / _ / (-1 1 (_) 1 (_ 1 < _ / 1
_ ._! \ _ ! \_! \_1__ \_ ,J \ _ / '-1-1'-'-1-I
Boot2Doc ker version 1.10 . 2, buil d mast er : 61 1be10 - Mon Feb 22 22 :47: 06 UTC
2016
Docker version 1. 10 . 2, build c3959bl
4.2 Project Atomic : la distribution Docker de Fedora
Pour être complet , listons rapidement les commandes de Docke r Machine qui
permettent de gérer le démarrage, l'arrêt et la suppression d'une machine :
Commande Description
docker-machine start machine Démarre une machine.
docker- machine stop machine Arrête une machine« gentiment».
docker-machine kill machine Arrête une machine de manière« brutale » <selon
les drivers, cette commande est parfois iden-
tique à la commande stop, par exemple pour
OpenStack).
docker-machine restart machine Redémarre une machine (équivalent à la corn-
mande stop suivie de la commande starù.
docker-machine provision machi ne Relance la création d'une machine existante. Cette
commande est principalement utilisée dans le
cas où la commande docker-machine create a
partiellement échoué.
docker-machine regenerate-certs Régénère et recopie les certificats TLS utilisés pour
machine sécuriser le démon Docker.
N ous savons maintenant tout ce qu'il faut pour créer des machines Docker à l'aide
de l'outil Docker Machine.
l. [Link]
Chapitre 4. Docker sur un sefVeur
une image hast Fedora conditionnée pour OpenStack sous le format qcow2. Nous
devrons ensuite la convertir en [Link] VDI, le format d'image VirtualBox.
Votre machine
VirtualBox
~Atomic
[
.·
l
Système de fichiers de votre machine
00.{
:_LJ ~edor~·Cloud xxx. vdi
1n1t.1so
l:J
0
c
::J Les étapes décrites dans la figure 4.6 sont les suivantes:
0
\.0
.-t
1. Dans la VM de travail, nous allons créer l'image de notre VM Atomic à l'aide
0
N de divers utilitaires.
@
....... 2. Ensuite, nous transférerons les images créées (un fichier VDI et un fichier ISO)
..c:
Ol vers notre machine hôte (celle que vous utilisez et sur laquelle est installé
ï::::
>-
0..
VirtualBox).
0
u 3. Ce transfert est très simple car il est géré par VirtualBox et Vagrant (il s'agit du
partage de fichiers que nous avons activé dans le chapitre 3 ).
4. Ensuite, nous utiliserons VirtualBox pour créer une VM Atomic à partir des
fichiers VDI et ISO.
5. Enfin, nous pourrons nous connecter sur cette VM Atomic pour quelques
opérations additionnelles.
4.2 Project Atomic : la distribution Dock er de Fedora
Téléchargeons l'image
C onnectez-vous à notre VM de travail et téléchargez (à l'aide de Firefox qui est
installé) l'image depuis le site du projet Fedora:
[Link]
- -
this.
C réez e nsuite dans votre répertoire courant un réperto ire nommé atomic, dans
lequel nous allons placer les d ifférents éléments dont nous aurons besoin :
$ mkdir at omic
$ cd at omi c
"'Cl $ pwd
0
c
:::i
~
,.,
"O
1 /home/vargra nt/ atomi c
0 [Link];
\.0
.-t ~
Placez dans ce répertoire le fichier QCOW 2 que vous venez de télécharger. Si vous
0 V
N V avez gardé le che min par défaut de Firefox, la commande suivan te devrait con venir :
'ii
@ ·c
B
.......
..c
O'l
ï:::::
:::;
CO
c
0
1 $ mv -/Téléchargements/* . qcow2 .
>- c
o. c
0 ·3ù Lançons maintenant la commande de conversion :
u :::;
"O
0
....
c.
~ $ qemu-img convert - f qcow2 Fedora -Cl oud-Atomic -23 -20160420 . x86_64.qcow2 -0
~
:::;
rS
1 vd i Fedora -Cloud-At omic -23 -20160420 . x86 64. vdi
1
"O
0
c Attention, la commande ci-dessus utilise une version donnée de l'image Fedora.
8 C elle-ci peut être différente dans votre cas.
(Ç)
Chapitre 4. Docker sur un se1Veur
Nous devons ensuite préparer les fi chiers de configuration (ce sont les équivalents
du fichier VagrantFile de Vagrant). Ceux-ci permettent de nommer la machine qui
sera créée, mais aussi de définir le mot de passe de l'utilisateur par défaut.
Vous devez donc éditer deux fichiers : meta-data et user-data.
$ vi met a-data
instance -i d: atomic - host -sampl e
l ocal - hostn ame : at omic . samp l [Link]
$ vi user-data
#cl oud -conf ig
password : atomi c
ssh_pwaut h: True
chpasswd : ( expire : False }
l:l
$ gen i so i mage -output i ni t .i so -volid ci da t a -jol iet -rock user -da t a meta -da ta
0 !: -i nput -charset not specified, using utf- 8 (detected in l oca l e set ti ngs)
c
:::i Total t ra nsl at ion ta ble si ze : 0
0
\.0
Total rockridge attr i but es bytes : 331
.-t Tota l di rectory bytes : 0
0
N Pa th ta bl e size(bytes) : 10
@ Max brk space used 0
.......
..c 183 ext en t s written (0 MB)
O'l
ï:::::
>-
0. Et maintenant transférons ces fichiers sur notre h ôte pour passer à l'étape de
0
u création de la VM avec VirtualBox :
Voilà ce que devrait contenir votre répertoire de travail Vagrant sur votre machine :
l. [Link]
4.2 Project Atomic : la distribution Docker de Fedora
À l'aide des fichiers VDI et ISO, la création de la machine virtuelle se fait en mode
graphique avec VirtualBox.
l:J
0
c
::J
~
,.,
"O
0 c::;
\.0
.-t
0
.,.,
~
[ ~xpert Mode J < !!_ack !!ext > J[ Cancel
N
'~
@ ·c
....... B::;
..c: CO
Figure 4 .9 - Création d'une machine virtuelle
Ol c
ï:::: 0
>- c
o.. c
u
0 ·3
<.)
::;
"O Nous allons maintenant définir la mémoire disponible pour cette machine v irtuelle.
0
.....
c. N ous allouons ici 4 G o de RAM, mais vous êtes libre de laisser la valeur par défaut
~
~
::;
proposée par VirtualBox, car elle sera suffisante pour cet exercice.
rS
1
"O
0
c
8
(Ç)
Chapitre 4. Docker sur un sefVeur
Memory size
Hard disk
If you wish you can add a virtual hard disk to the new
machine. '!bu can either create a new hard disk file or
select one from the list or from another location using the
folder icon.
1 ~ G~eral ------i_ls_t_o_ra_g_e_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _~
System ~torage Tree Attributes
~
Information
fi:ii Fedora-Cloud-Atomic-23-201... Type: Image
rlfJ Networlc O Please choose a virtual optical disk file
!) Serial Ports
r; USB
Look in: J ~ /home/pyc/Development/Worlcspaces/atomic : I + + +!:.Hill
Il Computer
i;'.J Shared Folde
ln pyc
ILj User Interface
Paramétrage du réseau
Nous vous proposons de configurer la VM pour qu'elle expose son port 22 sur l'hôte
via le port 9022. C eci nous permettra de nous connecter à cette VM à l'aide d'un
client SSH (et ainsi de ne pas souffrir des problèmes de clavier américain).
O Atomic host - Settings x
-
Storage
~ Audio 1 ~ame:
9 A~vanced
./ çable Connected
!r'.j User Interface
1 Eort Forwarding
_J~------
[ Qçancei l [ . .QK [
l:J
0
c
::J
0
\.0 1Q s;ancel 11 . ,QK
.--1
0
N
@
.......
Figure 4 . 1 5 - Association des ports réseau de l'hôte et de la VM
..c:
O'l
ï:::: Configurez les redirections de ports, comme cela est indiqué à la figure 4.15.
>-
0..
0
u Nous sommes maintenant prêts à nous connecter à notre VM Atomic.
1 $ ss h · p 9022 fe dora@local ho st
4.2 Project Atomic : la distribution Dock er de Fedora
Sous Windows, vous pouvez utiliser un outil comme putty si vous ne disposez pas
d'une ligne de commande.
Une fois la machine lancée, vous pouvez constater que Docker est déj à installé en
lançant la commande docker i nfo dont nous verrons qu'elle donne des informations
sur l'installation du moteur de conteneurs:
Vous pouvez noter dans le listin g ci-dessus que l'espace alloué pour les données
Docker n'est que de 2 Go. Dans un environnement réel, cette taille est très rapidement
atteinte. C'est la raison pour laquelle nous avons créé un nouveau d isque de grande
capacité.
C eci va nous permettre d'aborder un sujet important: la configuration du stockage
de données Docker.
approprié pour un système réel car c'est très consommateur de ressources, ce qui
dégrade les performances.
Heureusement, grâce à sa conception, Atomic est correctement préconfiguré avec
le mode de production (direct,lvm), bien que le disque image par défaut soit trop petit
(à peine 2 Go pour le stockage des blocs).
C 'est la raison pour laquelle nous avons créé un disque additionnel. Nous allons
maintenant étudier comment installer ce nouveau disque en créant un nouveau volume
group.
1 $ sudo fdis k -1
Le voici:
À ce stade, le disque est accessible depuis l'OS, mais pas alloué à Docker qui
s'appuie sur un volume group par défaut nommé atomicos et de taille restreinte :
$ sudo vgdisp l ay
-- - Volume group
VG Name atomicos
System ID
Format l vm2
VG Size 5. 70 GiB
l:J PE Size 4 .00 MiB
0
c
::J
0 N ous allons donc en créer un nouveau en utilisant le disque que nous avons ajouté
\.0
.-t
à notre machine virtuelle lors de sa création.
0
N Pour ce faire, nous allons en premier lieu acquérir les droits root :
@
.......
..c:
O'l
ï:::: 1 $ sudo su
>-
0..
0 Ensuite, nous allons modifier le fichier de configuration de l'utilitaire docker,
u
storage,setup :
Vous pouvez constater que le volume de stockage alloué aux données est mainte-
nant de 8,577 Go contre 2,085 Go. Sans entrer dans le détail du fonctionnement du
script docker-storage-setup, il s'agit par défaut de 40 % de l'espace disque physique qui
a été ajouté (nos 20 Go). Il est évidemment possible de modifier la configuration du
script pour obtenir d'autres résultats 1•
En résumé
Dans ce chapitre, nous avons appris comment installer Docker sur un hôte en
utilisant deux types de solutions différentes. Ceci nous a permis d'aborder l'usage de
l'un des outils de l'écosystème Docker (Docker Machine ). Nous nous sommes aussi
intéressés à la distribution Linux Atomic et, par l'intermédiaire de cet exemple, à
la configuration de devicemapper, un pilote de stockage (storage driver) majeur pour
l:l
0 Docker.
c
0
:::i Il est temps à présent de créer nos premiers conteneurs et de jouer avec la ligne de
\.0
.-t
commande Docker.
0
N
@
.......
..c
O'l
ï:::::
>-
0.
0
u
run ~
/ R:ning ~
start ~ stop kill
Créons un conten eur nginx 1 • Il s'agit d'un conteneur exécutant le serveur web open
source Nginx. Notez que l'image nginx est un official repository du Docker Hub, c'est-
à-dire une image certifiée par l'entreprise Docker lnc.
Sans entrer dans le détail à ce stade, vous noterez que n ous passons trois paramètres
à cette commande r un :
l:J
• -p 800 0 : 80 spécifie comment le port 80 du serveur web, ouvert à l'intérieur du
0
c conteneur, doit être exposé à l'extérieur (sur notre hôte ). N ous reviendron s par
:i
0 la suite sur ces problématiques de gestion du réseau. À ce stade, nous retiendrons
\.0
.-t que le port 80 du serveur web sera exposé sur le port 8000 de l'hôte .
0
N
• -d indique que le conteneur doit s'exécuter en mode démon, c'est-à-dire non
@
....... bloquant. Sans ce paramètre, la ligne de commande serait bloquée et affich erait
..c
en les logs du serveur web.
ï:::::
>- • ngi nx correspond au nom de l'image qui va ê tre utilisée pour instancier le
0.
0
u conteneur.
l. [Link]
S. 1 Le cycle de vie du conteneur a
Unable to find image 'nginx : l atest' l ocal l y
l at est : Pul l i ng fro m libr ary / nginx
9ee l 3ca3b908 : Pu l l complet e
23cb15b0f cec : Pull complete
62df5el7dafa : Pu ll compl ete
d65968claa44 : Pu l l compl ete
f5bbl dd dc876 : Pull comp l et e
1526247f349d : Pull compl ete
2e5 18e3d3fad : Pu ll complete
Oe07123e6531 : Pull compl et e
21656a3c1256 : Pu l l complete
f608475c6c65 : Pu ll compl ete
lb6c0a 20b353 : Pull compl ete
5328 f dfe 9b8e : Pu ll com plete
Digest :
sha256 : a79db4b83c0dbad9542d5442 00 2ea294aa77014a3df a67 160d8a5587 4a 55 20cc
Stat us : Downloaded newer i mage for ng i nx : latest
050e5c557d8a7a7ed37508c4cf35d260844ef75bf ae5 2f5bdd2302dac7b78806
J Wekome to n9inx !
Welcome to nginx!
~ you see this page, the nginx web server is successfully installed and working.
Further configuration is required.
For online documentation and support please refer to [Link].
Commercial support is available at [Link].
Identifier un conteneur
Pour déterminer cet identifiant, nous utiliserons la commande ps.
1 $ docker ps
C ette commande liste tous les conteneurs en cours d'exécution de même que
d'autres informations utiles :
C'est la dernière étape du cycle de vie de notre conteneur. Tentons de stopper n otre
conteneur.
$ docker rm 855bbd5e9823
Er ror respons e from daemon : Can nat destroy conta i ner 855bbd5e9823 : Conflict.
You can not remove a ru nn i ng cont ai ner . St op the container before at tempting
remov al or use -f
Error : failed to remove conta in ers : [8 55bbd5e9823 J
Docker nous indique que nous ne pouvons pas détruire un conteneur qui n'est
pas stoppé. C omme cela est indiqué sur la figure 5.1, nous devons d'abord stopper le
conteneur avant de le détruire.
Cette fo is, docke r ps -a montre que notre conteneur n'existe plus au niveau du
système, ce que confirme un ls /var/lib/docker/containers/.
Notez qu'il est possible de forcer la destruction d'un conteneur Up en utilisant, comme
le suggère le message d'erreur plus haut, le paramètre - f (ou - - force). Ce paramètre
provoque l'envoie un SIGKILL (comme pour la commande ki 11 ), ce qui a pour effet
de stopper le conteneur avant de le détruire.
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED
2ab2ba l 543ce nginx "n gi nx -g 'daemon of f " 8 seconds ago
STATUS PORTS NAM ES
Created roma ntic_nobel
5.2 Accéder au conteneur et modifier ses données -----------------11031
Il ne reste alors qu'à démarrer notre conteneur en utilisant l'habituelle commande
s t art.
Nous avons parcouru dans cette section l'ensemble du cycle de vie d'un conteneur.
Néanmoins, le conteneur que nous avons utilisé était relativement inintéressant. Nous
devons donc maintenant aborder deux questions :
• Comment configurer le comportement d'un conteneur et le faire, par exemple,
interagir avec son système hôte ?
• Comment créer une image originale qui fournisse un service correspondant à
nos besoins ?
..
5.2 ACCEDER AU CONTENEUR ET MODIFIER SES
..
DONNEES
Nous allons aborder dans cette section différents points d 'intégration entre le conte,
neur et son système hôte :
• la connexion en mode terminal avec le conteneur ;
• la gestion des volumes et la manière d'assurer la persistance de données sur
l'ensemble du cycle de v ie d 'un conteneur (y compris après sa destruction) ;
• la configuration des ports IP.
Nous ne traiterons pas des liens réseaux entre les conteneurs. Cet aspect sera traité
dans la quatrième partie de cet ouvrage sur la base d'exemples significatifs.
l:J
0
c
::J
~
,.,
"O
0 c::;
\.0
.-t .,.,
~ 5.2.1 Connexion en mode terminal
0
N
'~
@ ·c Dans le paragraphe précédent, nous avons utilisé une image générique prise depuis le
....... B::;
..c: CO Docker Hub sans la modifier. En pratique, lancer un conteneur sans le modifier n'a
Ol c
ï:::: 0
>- c aucun intérêt.
o.. c
u
0 ·3
<.) Nous allons reprendre notre image nginx en modifiant les pages retournées par le
::;
"O
0
.....
c.
serveur web.
~
~
::;
rS
1
"O
0
c
8
(Ç)
Chapitre 5. Conteneurs et images
La page que nous avons vue jusqu'à maintenant se trouve (au sein du conteneur)
dans le répertoire /usr/share/nginx/html.
Comment la modifier ?
Comme nous allons le voir plus bas, Docker offre la possibilité de lancer des
commandes dans un conteneur actif tout en obtenant un lien de type pseudo~terminal.
En premier lieu, démarrons un nouveau conteneur.
Vous noterez que nous venons d'utiliser un nouveau paramètre - -name pour la
commande r un. Celui~ci permet de changer le nom d'un conteneur en utilisant un
alias généralement plus simple à mémoriser que l'UUID ou le nom donné par défaut
par Docker.
l:J
1 $ docker exec -t -i webserver /bin/bash
0
c La commande exec permet de démarrer un processus dans un conteneur actif.
::J
0 Dans notre cas, n ous lançons un nouveau terminal (bash) en l'associant (grâce aux
\.0
.-t
0
paramètres - i et -t ) au flux d'entrée (STDIN) et à un pseudo~terminal. L'exécution
N
de la commande ouvre un prompt Unix qui permet alors de naviguer à l'intérieur du
@
....... conteneur.
..c:
O'l
·;::
>-
0..
0
root@28314fdbd549 : /# hostname
u 28314fdbd549
root@28314fdbd 549 : /# l s
bi n boot devetc home l i bl i b64 media mnt optproc root run sbin srv
sys t mp usr var
Pour co nfirmer que nous sommes bien à l'intérieur du conteneur, nous allons
modifier la home page du serve ur web. La commande suivante écrase le contenu du
fichier HTML par défaut avec une simple chaîne de caractères« Je suis dedans» .
M ozill.a Firefox c )(
[Link] 8000/ )( 1 +
~) Localhost·8000 V ~1 » -
Je suis dedans
Bien que fonctionnelle, cette approche n'est pas franchement efficace car il n'est
pas réellement possible de modifier des quantités importantes de données. Par ailleurs,
la destruction du conteneur entraînera automatiquement la perte des modifications
opérées.
Les volumes' sont le moyen qu'offre Docker pour gérer la persistance des données au
sein des conteneurs (et en relation avec leur machine h ôte).
Comme nous l'avo ns vu précédemment, la page d'accueil du serveur web Nginx
l:J se trouve dans le répertoire /usr/share/nginx/html/[Link]. Définissons un volume
0
c ~
,., correspondant à ce chemin à l'aide du paramètre -v de la commande run .
::J
"O
0 c::;
\.0
.-t
0
N
.,.,
~
1 $ docker run -p 8000 :80 --name webserver -d -v / usr/share/nginx/ html ng i nx
'~
@ ·c
....... B::;
..c: CO
Attention, si vous n'avez pas supprimé le conteneur webserver créé dans le
Ol c
ï:::: 0
>- c paragraphe précédent, vous noterez que la tentative d'en créer un nouveau (avec
o.. c
u
0 ·3
<.)
le même nom) se solde par une erreur « Error response from daemon: Conflict. The
::;
"O
0
.....
name "webserver" is already in use by container ... You have ta remove (or rename) that
c.
~ container ta be able ta reuse that name. »
~
::;
rS
1
"O
0
c
8
(Ç) 1. Veui llez-vous reporter au chapitre l pour une explication du concept de volume de conteneur.
Chapitre 5. Conteneurs et images
"Mounts ": [
{
"N ame ":
"c29b645f024f59988c24dbb0564a6f893da5lbl7ccd687dfbf794ef4143c48f5 " ,
"Sou rce" : "/var/ l i b/docker/volumes
/c29b645f024f59988c 24dbb0564a6f89 3d a5lbl 7ccd687d fbf 794ef4143c48f5/_data " .
"Des t i nation " : "/ usr/share/ngi nx/ html ",
"Driver" : "loca l ",
11
Mode 11
:
1111
,
"RW ": tr ue
"'Cl
identifié par le paramètre Source.
0
c RW Indique que le volume (à l'intérieur du conteneur) est reod-write
:::i
0 (il peut être lu et modifié).
\.0
.-t Si no us n ous plaçons dan s le répertoire obtenu via la commande i nspe ct , nous
0
N constatons effectivement qu'il contient le fic hier [Link] que nous avions trouvé
@
.......
précédemment dans le réperto ire /usr/share/ngi,nx/html à l'intérieur du conteneur.
..c
O'l
'i:
>-
0. $ sudo ls /var/ l i b/doc ker/volumes
0
u /c29b645f024f 59988c24dbb0564a6f893da5 lbl7ccd687d fbf 794ef4143c48f5/_data
1 50x .h t ml i ndex . html
l. [Link]
5.2 Accéder au conteneur et modifier ses données -----------------11071
Attention, notez que nous sommes contraints d'utiliser la commande sudo pour
disposer des droits root. Caccès au système de fichiers Docker n'est évidemment pas
accordé sans ce niveau de privilège.
$ sudo su
$ ec ho "J e modif i e un vol ume " > /va r / l ib/docker/vol ume s
/6ld5 b52ba3385203910 dd8237700de02056 a40a23a f 3le3b5b62d95 f 63117d06/ data /index. html
1 $ exit
Le résultat peut une fois de plus être visualisé à l'aide de notre navigateur web.
M ozilla Firefox Cl )(
[Link] :8 0 00/ )( l +
+ Localhost 8000 v(! I » --
Je modifie un vo lume
Figure 5.4 - Home page de Nginx modifiée sur l'hôte
Il est possible, à la place du driver local de Docker, de mon ter un répertoire de l'hôte
dans le conteneu r. N ous allons en premier lieu créer ce réperto ire dans l'espace de
travail de l'utilisateur vagrant.
Encore une fois, pensez à vérifier à l'aide de la commande docker ps - a que vous
n'avez pas de conteneur existant qui porte déjà le nom « webserver » ou qui écoute
sur le mê me port 8000. Si c'est le cas (ça devrait l'être si vous avez suivi les exercices
précédents pas à pas), pensez à supprimer ce conteneur à l'aide des commandes
st op puis rm.
Mozilla Firefox c )(
[Link] 8000/ )( +
~) Localhost 8000 V ~1 )) --
Un fi chier su r le hast
Pourtant seul le port 80 est accessible au niveau de l'hôte et, comme nous l'avons
indiqué, il est mappé sur le port 8000.
Nous reviendrons plus en détail sur les problématiques de réseau et sur l'adresse
IP associée ici au port exposé : [Link] 1• À ce stade, notez seulement qu'il s'agit de
l'adresse par défaut à laquelle Docker attache le port ainsi ouvert sur l'hôte.
$ docker rm -f webserver
$ docker run -P --n ame webserver -d ngi nx
$ docker ps
CONTAI NER ID IMAG E COMMA ND CREA TE D
97066be7 b321 nginx "n ginx -g 'daemon off " 4 minutes ago
STATUS PORTS NAM ES
Up 3 minutes 0. 0. 0. 0:32769->80/tcp. 0. 0. 0.0:32768 ->443 /tcp webserver
Lors que le paramètre - P est utilisé, Docker va associer les ports du conteneur avec
les ports disponibles sur l'hôte (choisis au hasard).
Dans le cas ci~dessus, le port 80 est associé au port 32769 de l'hôte.
l. La notion d'adresse "[Link]" par rapport à" 127.0.0. l " est expliquée dans le chapitre 3 ( § 3.2.3 ).
5.3 Construire une image Docker originale --------------------8
5.3.1 Lister les images
$ docker images
RE POSITORY TAG IMAGE ID CREATED
ng i nx l at es t 5328fdf e9b8e 3 wee ks ago
VIRTUA L SI ZE
133 .8 MB
C omme vous po uvez le constater, notre image nginx est bien là.
Si vous ajoutez le paramètre - a (pour all) à cette commande, vous constatez que la
liste est net tement plus longue :
$ docker images -a
RE POS ITORY TAG IMAGE ID CREATED
VIRTUA L SI ZE
ng i nx l at es t 5328f df e9 b8e 3 wee ks ago
133. 8 MB
<none> <none> f608475c6c65 3 weeks ago
133 .8 MB
<none> <none> l b6c0 a20b353 3 weeks ago
133 .8 MB
<none> <none> 21656 a3c l256 3 weeks ago
133.8 MB
<none> <none> Oe07123e6531 3 weeks ago
133 .8 MB
<none> <none> 2e518e3d3f ad 3 weeks ago
133 .8 MB
<none> <none> 1526247f349d 3 weeks ago
125. l MB
l:J
<none> <none> f5bbldddc876 5 weeks ago
0 125.1 MB
c ~
,.,
:J
"O
<none> <none> d65968cl aa44 5 weeks ago
0 c::;
\.0
125.1 MB
.-t
0
.,.,
~ <none> <none> 62df5e17dafa 5 weeks ago
N
'~
125. 1 MB
@ ·c <none> <none> 23cb15büfcec 5 weeks ago
....... B
..c:
::;
CO 125 .1 MB
Ol c <none> <none> 9ee13ca3b908 5 weeks ago
ï:::: 0
>- c
o.. c 125.1 MB
u
0 ·3
<.)
::;
"O
0
Mais d'où viennent ces images qui n'ont pas de nom, mais uniquement un U UID ?
.....
c.
~ S i vous lisez attentivement la section « C réer et démarrer un conteneur », vous
~
::;
remarquez que les mêmes identifiants étaient présents lors du chargement de l'image
rS
"O
1 ( lors de la création de notre premier conteneur) .
0
c
8 C es images sans n om sont ce que l'on appelle des images interméd iaires. Elles
(Ç) correspondent aux couches dont une image est constituée (voir le chapitre 1). Nous
Chapitre 5. Conteneurs et images
verrons plus tard comment ces images intermédiaires sont utilisées lors de la création
d 'une n ouvelle image.
Effaçons notre image nginx avec la commande docke r rmi (à ne pas confondre avec
docker rmqui, comme nous l'avons déjà vu, est réservé aux conteneurs) :
Er ror respo nse f rom daemon : conflict : unable to remove repos i to ry ref erence
"ngi nx " (mus t force) - cont ainer 050e5c55 7d8a is usi ng its refe r enced image
5328fdf e9b8e
1 Error : failed to remove images : [nginx ]
Il n'est en effet pas possible de supprimer une image pour laquelle des conteneurs
sont encore présents. Si l'on se souvient de la structure en couches des conteneurs, on
comprend que cela n'aurait effectivement pas de sens. Il vous faut donc détruire tous
les conteneurs.
nginx i::l
55MB
55MB
letest 55MB
Maintenant, créons une image avec la dernière version (latest) de Nginx, comme
nous l'avons déjà fait précédemment :
Attention à ne pas utiliser le même port TCP que pour notre conteneur webser,
ver1 7, afin d'éviter un message d'erreur déplaisant.
Maintenant que nous avons vu comment obtenir une image depuis le Hub, voyons
l:l
0 comment en créer une qui nous convienne et intègre des modifications par rapport à
c
:::i une image de base.
0
\.0
.--t
Créons donc un conteneur nginx :
0
N
@
.......
..c
1 $ doc ke r r un -p 8000: 80 -- name webser ver -d ngi nx
O'l
'i:
>- C omme nous l'avons fait dans la section 5.2, ouvrons un terminal sur le conteneur
0.
0 pour modifier la page d 'accueil de Nginx :
u
N ous venons de créer une nouvelle image « nginxhello », à partir de laquelle nous
pouvons maintenant créer de nouveaux conteneurs, par exemple :
M ozilla Firefox c )(
Cette technique de création d'image, bien que fonctionnelle, n'est utilisée que
pour des besoins de debugging, comme nous le verrons dans la prochaine section. On
lui préfère la création d'image à partir de Dockerfile.
"'Cl
0
c ~
,.,
0
:::i
"O 5.4 LE DOCKERFILE
[Link];
\.0
.-t ~
0 V
N V Le Dockerfile est probablemen t l'une des raisons du succès de Docker dans le domaine
'ii
@ ·c des conteneurs. Voyons en pratique ce dont il s'agit.
....... [Link];
..c CO
O'l c
0
ï::::: c
>-
o. c 5.4.1 Les risques d'une création d'image par commit
u
0 ·3ù
:::;
"O
0
.... Dans ce chapitre, nous avons créé un conteneur N ginx dont nous avons ch angé la
c.
~ page par défaut ([Link]). Nous avons vu une technique pour créer un conteneur
~
:::;
à l'aide de la commande commit, c'est-à-dire en sauvegardant l'état d 'un conten eur
rS
1 précédemmen t créé à partir d'une image de base, puis modifié manuellement.
"O
0
c
8 Le défaut de cette technique réside dans la documentation du processus de création
(Ç) de l'image. Il est possible de distribuer cette image de conteneur web, mais la recette
Chapitre 5. Conteneurs et images
pour le créer n'est pas n ormalisée. O n pourrait certes la documenter, mais rien n e
permettrait d'avoir l'assuran ce que l'image a insi produite soit bien la résultante de
la séquen ce d 'instructions documentées. En cla ir, quelqu'un pourrait avoir exécuté
d'autres commandes (non documentées) pour créer cette image et il ne serait pas
possible de prévoir les con séquen ces de son usage.
C'est justement le propos des Dockerfile : décrire la création d'images de manière
forme lle.
Dans cette section n ous allons programmer un [Link] réalisant la création d'un
con ten eur ayant les mêmes caracté ristiques que notre exemp le Nginx.
En premier lieu, créez un réperto ire vide.
Dans ce répertoire, n ous allons mettre deux fichiers :
• un fichier Dockerfile ;
• un [Link] [Link].
Dans ce dernier [Link], nous allons écrire le texte suivant (par exemple, à l'aide de
l'éditeur v i) :
$ docker images
RE POSITORY TAG IMAGE ID CREATED
SIZE
nginxhello l atest a8f7c2 454f7 f About a mi nute ago
93 .4 MB
<none> <none> cc0b89 24 5d0d 15 min utes ago
93 .4 MB
<none> <none> e3d6892f8073 3 months ago
133 .8 MB
ngi nx la t est 4045d5284714 4 months ago
133 .8 MB
ngi nx 1. 7 d5acedd7e96a 12 mon ths ago
93 .4 MB
Un accès à l'URL [Link] ost:8000 nous confirme que notre serveur web est
actif et que sa page par défaut correspond bien au texte que nous avions mis dans le
fichier [Link].
N ous venons de créer notre premier Dockerfile et, grâce à celui-ci, nous pouvons :
• créer une image permettant de produire des conteneurs N ginx modifiés à loisir ;
• distribuer la recette pour fabriquer cette image.
Full Description
Figure 5.10 - Lien vers le Dockerfile de l'image de base nginx sur le Docker Hub
Notez l'identifiant de cette couche : d5ac edd 7e96a. N ous l'avons déjà vu aupara-
vant car il s'agit de celui de l'image de base n ginx en version 1.7:
$docke r images
REPOS ITORY TAG IMAG E ID CREATED
SIZE
ngi nx 1. 7 d5acedd7e96a 12 months ago
93 .4 MB
N otre image finale est donc constituée d'une série d'images qui peuvent être soit
complètement originales, soit h éritées d'une image existante par l'intermédiaire de
l'instruction FROM .
Il est d'ailleurs possible de visualiser l'ensemble des couches d'une image donnée
grâce la commande doc ke r hi story :
.-t
0
.,.,
~
"daemon o 0 B
N
'~ abdbd9163c9b 12 months ago /bin/sh -c #(nop) EX POSE 443/tcp
@ ·c
B 80/tcp 0 B
....... ::;
..c: CO e5 51 fl54c24f 12 months ago /bin/ sh -c #(nopl VO LUME
O'l c
·;:: 0
c [/var/cac he/ng i nx] 0 B
>- c a33 f3c9e flc 4 12 months ago /bin/sh -c ln -sf /dev/stderr
o..
u
0 ·3
<.) /var/l og/ngi nx/ 0 B
::;
-0
0 bl ce25f2cd9c 12 months ago /bin/sh -c ln -sf /dev/stdout
.....
c.
~
/var/l og/ngi nx / 0 B
~ 3c5fee6e68b3 12 months ago /bin/sh -c apt- get upda te &&
::;
rS apt -get i nst 8 .38 MB
1 4446b7f2ac03 12 mont hs ago /b in /sh -c #( nop ) ENV
-0
0
c Ngi nx_VERSION=l.7 .1 2-1- 0 B
8 e97439968948 12 months aga /bin/sh -c ec ho "deb
(Ç) http : //n gi [Link]/package 221 B
Chapitre 5. Conteneurs et images
Là encore, vous remarquerez l'image a8f7 c 2454f7 f qui correspond à notre instruc~
tion copy. Si vous vous reportez au journal (log) de l'instruction docke r bui l d, un peu
plus haut, vous verrez que l'identifiant correspond.
En résumé
Nous avons vu dans ce chapitre ce qu'était un conteneur en pratique : comment le
créer, le supprimer, le démarrer et l'arrêter. Nous avons vu que les conteneurs étaient
produits à partir de moules que représentent les images. Nous avons enfin étudié
comment créer de nouvelles images qui intègrent des spécificités par rapport à des
images de base téléchargées d'habitude depuis le Docker Hub. Nous nous sommes
aussi penchés sommairement sur la notion de Dockerfile.
À l'issue de ce chapitre, vous maîtrisez les concepts et commandes fondamentaux
du moteur Docker. Il est temps de monter en puissance et de mettre en pratique ces
connaissances à travers des exemples de plus en plus complexes.
l:J
0
c
:J
0
\.0
.-t
0
N
@
.......
..c:
Ol
·;::
>-
0..
0
u
....
TROISIEME PARTIE
Apprendre Docker
Cette troisième partie, qui peut aussi servir de référence, vise à expliquer en détail, à
travers des exemples pratiques :
• les commandes du client Docker ;
• les instructions des Dockerfile que nous avons commencé d'étudier dans le
dernier chapitre de la précédente partie.
Nous avons choisi de découper cette partie en trois chapitres qui peuvent être lus
de manière no n séquentielle :
• le chapitre 6 montre l'usage des commandes principales du client Docker.
L'objectif ici n'est pas d'être exhaustif, mais de montrer et d'expliquer les
l:J
0 commandes essentielles (celles dont on se sert tous les jours) à travers des
c
:J
~
,.,
0 "O exemples utiles ;
c::;
\.0
.-t .,.,
~ • le chapitre 7 est consacré aux principales instructions des Dockerfile, c'est-à-dire
0
N
'~
celles qui sont présentes dans 95 % des fichiers Dockerfî.le que vous aurez à lire ;
@ ·c
....... B::;
• le chapitre 8 se penche, quant à lui, sur des commandes et instructions
..c: CO
Ol c Dockerfî.le plus avancées.
ï:::: 0
>- c
o.. c
0 ·3 Chacun de ces chapitres peut être lu individuellement. Des références croisées
u <.)
::;
"O
0
permettent de passer d'un chapitre à l'autre pour acquérir progressivement la maîtrise
.....
c. de Docker.
~
~
::;
Nous conseillons cependant de lire les chapitres dans leur ordre naturel en
rS
"O
1
commençant par le chapitre 6.
0
c
8
(Ç)
"'O
0
c:
:::i
0
\.0
r-1
0
N
@
......,
..c:
en
·;::
>-
0..
0
u
6
Prise en main
du client Docker
Dans ce chapitre, nous vous présenterons les commandes usuelles du client Docker
et leurs options les plus importantes.
À travers les différe nts chapitres précéd en ts, n ous avon s déjà abordé certaines de ces
commandes. Notre objectif ici est d'en présenter quelques autres par l'intermédiaire
d'exemples simples e t ciblés.
Le but de ce chapitre est de faire atteindre au lecteur un bon niveau de maîtrise de
cette ligne de commande que nous utiliserons intensivement dans la suite de ce livre.
l:J
0
c
::J
~
.
., 6.1 INTRODUCTION À LA CLl 1 DOCKER
"O
0 c::;
\.0
.-t
0
.,.,
~ Dans ce premier paragraphe, n ous allons donner quelques informations complémen~
N
·~ taires sur le clie nt Docker, à savoir :
@ ·c
B
.......
..c:
::;
CO
• les variables d 'en vironnement qu'il utilise (et qui permettent d'en modifier la
Ol c
ï:::: 0
c configuration) ;
>- c
o.. • la structure génériq ue des options des différents outils Docker.
u
0 ·3
<.)
::;
"O
0
.....
c.
~
~
::;
rS
1
"O
0
c
8
(Ç) 1. Command Line In terface= la ligne de commande
J 1241 - - - - - - - - - - - - - - - - - - - - Chapitre 6. Prise en main du client Docker
La ligne de commande Docker, qui permet l'exécution des commandes Docker, utilise
un certain nombre de variables d'environnement. En modifiant ces dernières, le
comportement des commandes Docker est affecté. Le tableau 6.1 décrit de manière
exhaustive les variables d'environnement Docker. Nous verrons ensuite un exemple
illustrant l'impact fonctionnel d'une telle variable.
$ docker ps
CONTAINER ID IMAGE COMMAN D PORTS STATUS
c7ccla31d8f0 ngin x "n gi nx -g 'daemon off " 80/tcp . 443/tcp Up 12
1 minutes
Il est bien sûr possible de spécifier d'autres paramètres de configuration. Pour plus
de détails reportez-vous à la documentation en ligne de Docker.
Les commandes Docker peuvent être paramétrées grâce à des options. C haque option
a une valeur par défaut, si bien que lorsque l'option n'est pas spécifiée, c'est sa valeur
l:J
0 par défaut qui sera appliquée.
c
::J
~
,.,
"O
0 c::; En termes d'écriture, les options sont soit représentées par une lettre (dans ce cas
\.0
.-t
0
.,.,
~ elles sont spécifiées par un simple tiret « - »), soit par plusieurs lettres (dans ce cas
N
'~ nous utilisons un double tiret « - - » ). Par exemple :
@ ·c
....... B::;
..c: CO
Ol c
$ docker run -i
1 $ docker run --detac h
ï:::: 0
>- c
o.. c
u
0 ·3
<.)
::;
"O
0
.....
c.
Généralement, une option définie par un simple tiret est un raccourci du nom
~ d'une option avec un double tiret. Par exemple, les deux options suivantes sont
~
::;
rS équivalentes :
1
"O
0
c
8 $ docker run -m 5M
(Ç) 1 $ docker run --memory 5M
J 1261 - - - - - - - - - - - - - - - - - - - - Chapitre 6. Prise en main du client Docker
Comme nous le constatons dans les exemples ci,dessus, certaines options ont une
valeur (par exemple, docker run -m 5M ) et d'autres non (par exemple, docker r un
-i ). En réalité, toutes les options ont une valeur, mais dans certains cas, il n'est pas
nécessaire de la spécifier ; tout dépend du type de l'option qui peut être Booléen,
Valeur simple ou Valeur multiple.
$ doc ker r un -i
1 $ docker r un -i=true
Dans la documentation des commandes Docker, les options de type Booléen sont
décrites par le format suivant :
1 {nomüption}
1 ( - 1--) (nomOpt i on} (=I ) (" (val eur J"I (val eur })
Par exemple :
$ docker run -m 5M
1 $ docke r run - -memory 5M
Valeur multiple
Une option de type Valeur multiple définit une option qui peut être utilisée plusieurs
fois ; on dit que l'option est cumulative.
Dans la documentation des commandes Docker, les options de type Valeur multiple
sont décrites par le format suivant :
1 (nomOpt i on}=[ J
{nomOption} définit le nom de l'option, par exemple - p.
Son modèle d'utilisation est identique à celui du type Valeur simple, à l'exception
du fait qu'il peut être répété autant que nécessaire. Par exemple :
La bonne pratique
Comme cela est indiqué dans les modèles ci,dessus ( =1), la valeur d'une option, quand
elle est donnée, peut soit être placée après un signe égal, soit après un espace ; ainsi
l:J
0 les deux écritures suivantes sont équivalentes:
c
::J
~
,.,
"O
0 c::;
\.0
.-t .,.,
~ $ docker run -m=5M
0
N
@
'~
·c
1 $ docker run -m 5M
....... B::;
..c: CO Toutefois, pour des raisons de lisibilité et de conformité avec le monde Unix, il
Ol c
ï:::: 0
c convient de n'utiliser le sigle égal que pour les options de type Booléen. Ainsi nous
>- c
o.. aurions :
u
0 ·3
<.)
::;
"O
0
.....
c.
~ $ docker run -i=tr ue
~
::; 1 $ docker run -m 5M
rS
1
"O
0
Toujours selon les modèles, la valeur d'une option peut être encapsulée par des
c
8 guillemets. Cependant, nous éviterons cette écriture, sauf si la valeur en question
(Ç) contient des espaces.
J 12sl-------------------- Chapitre 6. Prise en main du client Docker
..
6.2 LES COMMANDES SYSTEME
Dans cette section, nous allons présen ter ce que nous avons regroupé sous le terme de
« commandes système» . Il s'agit des commandes qui sont relatives au Docker Engine
dans son ensemble, soit pour piloter le démon , soit pour obtenir des informations sur
son fonctionnemen t.
C'est la commande permettant de contrô ler le démon Docker. N ous l'avons déjà
abordée dans le chapitre 3.
Évidemment, dans la plupart des cas, le démon est démarré automatiquement
par un gestionnaire de système (comme systemd pour CentOS ou REHL).
Par exemple, sous C entOS, la définition du service est stockée sous
/usr/ lib/systemd/system/[Link] :
[Serv i ce]
Type=not i fy
#the defaul t is not to use sys temd f or cgro ups because the delegate issues
st il l
# exists and systemd currently does not support the cgroup fea tu re set
l:J required
0
c # f or conta i ners r un by doc ker
::J
0 ExecSt art=/ usr/bin/doc ker daemon -H fd : //
\.0
.-t
0
N
@ N ous voyons que celle-ci fait appel à la commande docker da emon . Cette dernière
....... prend en paramètre de très nombreuses options relatives à différents sujets:
..c:
O'l
·;::
>- • authentification (plugins spécifiques et h eaders HTTP à ajouter aux requêtes
0..
u
0 REST du client Docker) ;
• paramétrage réseau (certificats, serveur ONS à utiliser, règles de forwarding IP,
etc.) que nous aborderons dans les chapitres 9 et 11 ;
• labels (dont nous parlerons dans le ch apitre 11 avec Swarm) qui permettent
de qualifier un hôte pour permettre l'application automatique de règles de
déploiemen t dans le cadre d'un cluster ;
• etc.
6.2 Les commandes système -----------------------11291
6.2.2 docker info
Affiche la version du client et du serveur (démon) Docker (pour peu que ce dernier
soit installé) :
$ docker vers io n
Client :
Version: 1. 11.l
API version : 1. 23
Go version : gol .5. 4
Git commit : 5604cbe
Bui lt : Wed Apr 27 [Link] 2016
OS/Arch : l inux/amd64
Server:
Version: 1.11 .1
API version : 1. 23
Go version : gol .5. 4
Git commit : 5604cbe
Bui lt : Wed Apr 27 00:34 :42 2016
l:J
0
OS/Arch : lin ux/amd64
c
::J
~
,.,
"O
0 c::;
\.0
.-t
0
.,.,
~ 6.2.4 docker stats
N
'~
@ ·c
....... B::; docker stats COPTIONSJ
..c: CO
Ol c
ï:::: 0
>- c
o.. c
u
0 ·3
<.)
Une instruction qui donne (un peu à la manière d'un to p sous Unix) des
::;
"O
0
.....
informations sur les conteneurs exécutés par le moteur :
c.
~
~
::;
$ docker st at s
rS
1 CONTA INER CPU % MEM USAGE / LI MI T MEM %
"O
0
c NET 1/0 BLOCK 1/0 PIDS
8 b7f69 l e522b8 0.00% 7.815 MB / 1. 929 GB 0.41%
(Ç) 5.213 kB / 4. 956 kB 6. 791 MB / 0 B 0
J nol-------------------- Chapitre 6. Prise en main du client Docker
Cette commande accepte notamment une option - a qui permet de visualiser tous
les conteneurs (sous-en tendu, même ceux qui son t à l'arrêt) et une option - -no- s tream
qui permet de n'afficher qu'un instantané (un snapshot en anglais) des statistiques qui
ne sont donc pas rafraîchies en temps réel.
6.2.5 docker ps
docker ps COPTIONSJ
Cette commande permet de lister les conteneurs actifs (par défaut) ou l'ensemble
des conteneurs avec l'option - a.
La commande est aussi à la base de l'astuce permettant d'effacer tous les conteneurs
et que nous avons vue dans le chapitre 5 :
1 $ docke r rm $(docker ps -a - q)
l:J
0
c Une commande qui permet d'affi cher les événements qui se produisent sur le bus
::J
0 d'événements Docker. Une fois activée, la commande (un peu à la manière d'un t a i l
\.0
.-t
0
- f sur un fichier) affiche les événements du moteur Docker concernant les conteneurs,
N
les images, les vo lumes et le réseau.
@
....... Par exemple, si nous lançons un conteneur (ici nommé « tiny_bassi ») et que nous
..c:
O'l
·;:: lui faisons subir une séquence d 'actions (ici pause, unpause, stop puis start ):
>-
0..
0
u
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b7f691e522b8 ng i nx "nginx -g 'daemon off " 3 mi nutes aga Up 3 mi nut es
0.0 . 0.0 :80 ->80/tcp , 443/tcp ti ny_bassi
$ doc ker pa use b7f691e522b8
b7f691e522b8
$ docker unpa use b7f69le522b8
b7f69 1e522b8
6.2 Les commandes système -----------------------El
$ docker stop b7f69 l e522b8
b7 f69 1e522b8
1 $ docker start b7f691e522b8
$ docker events
2016-05 -09T13 :16 : 24 . 768480481+02 :00 container pa use
b7f69 1e522b80b69ca4a01d9f267eb31717f95b4e029c9068620322c0e81ac12 ( i mage=nginx,
name=tiny_bass i l
2016 -05 -09Tl3 :16 : 29 . 567098215+02 :00 container unpause
b7f69 1e522b80b69ca4a01d9 f 267eb31717f95b4e029c9068620322cüe81ac12 ( i mage=nginx ,
name=tiny_bass i l
2016 -05 -09T13 :16 :34 . 573241379+02 :00 container ki l l
b7f69 1e522b80b69ca4a01d9 f 267eb31717 f95b4e029c9068620322c0e81ac12 ( image=nginx,
name=tiny_bass i , sig nal =l 5)
2016 -05 -09T13 :16 :34 . 619735796+02 :00 container die
b7f69 1e522b80b69ca4a01d9 f 267eb31717 f95b4e029c9068620322c0e81ac12 (exitCode=O ,
image=ng i nx , name=ti ny_bassi)
2016 -05 -09T13 :16 :34. 767099031+02 :00 network disco nnect
cdb6ff80d4f9ff518d907de596fbd6ed437a9d247c l edb8a6b0b4d24ef4d583d
(conta i ner=b7 f 691e522b80b69ca4a0 1d9f267eb31717f95b4e029c9068620322c0e81ac12,
name=bridge , t ype=br id ge)
2016-05-09Tl3 : 16 :34 . 813257612+02 :00 container stop
b7f69 1e522b80b69ca4a0 1d9f267eb3 1717f95b4e029c9068620322c0e81ac12 ( i mage=nginx ,
name=tiny_bass i l
2016 -05 -09T13 :16 :38 . 957730296+02 :00 network connect
cdb6ff80d4f9ff5 18d907de596fbd6ed437a9d 247c l edb8a6b0b4d24ef4d583d
(conta i ner=b7f691e522b80b69ca4a0 1d9f267eb31717f95b4e029c9068620322c0e8lacl2 ,
name=bridge , t ype=br id ge)
2016-05 -09Tl 3:1 6:39 . 16607 1968+02 :00 conta i ner start
b7f69 l e522b80b69ca4aüld9f267eb3 1717f95b4e029c9068620322c0e81acl2 ( i ma ge=nginx ,
name=tiny_bass i )
l:J
0 On remarquera les événements réseau qui sont implicitement déclenchés par l'arrêt
c
::J
~
,., et le démarrage du conteneur.
"O
0 c::;
\.0
.-t
0
.,.,
~
N
'~ À noter que, co mme n ous l'avons déjà expliqué, toutes les commandes du client
@ ·c
....... B::;
Docker correspondent à des API REST. Il est ainsi possible à des applications tierces
..c: CO
Ol
0
c de s'enregistrer sur l'API suivante qui va streamer les événements au format JSON:
ï:::: c
>- c
o..
0 ·3
u <.)
::;
"O
0
1 GET /events
.....
c.
~
~
::;
rS
1
6.2. 7 docker inspect
"O
0
c
8 docker inspect [OPTIONSl CONTAINERllMAGE [CONTAINERllMAGE...l
(Ç)
El------------------- Chapitre 6. Prise en main du client Docker
Cette commande, qui permet de stopper un conteneur, a aussi déjà été étudiée
dans le ch apitre 5. Elle accepte notamment une option - t qui permet de spécifier un
nombre de secondes à attendre avant de tenter un ki 11.
l:J
0
c
6.3.3 docker kill
:J
0
\.0
.-t 1 docker klll !OPTIONSI CONTAINER
0
N
@
.......
..c:
Cette commande, déjà évoquée au chapitre 5 , permet de forcer l'arrêt d'un
O'l
·;:: conteneur (un peu à la manière du célèbre ki 11 -9 pour un processus Unix).
>-
0..
0
u
6.3.4 docker restait
6.3.6 docker rm
La commande update a un lien avec les commandes create et run . Elle permet
en effet de mod ifie r les paramètres d'un conteneur alors que celui,ci est démarré.
Attention, il ne s'agit pas de modifier des paramètres de volume ou réseau, mais
uniquement la configuration des ressources allouées au conteneur, par exemple :
• -cpuset- cpu s pour le nombre de C PU ;
• -mpour la mémoire maximale disponible.
Il existe d 'autres paramètres dont les plus importants sont détaillés ci-dessous :
• - -en trypo i nt="" qui permet de surcharger l'instruct io n EN TRYPO IN T du
conteneur spécifiée dans le Dockerfile. Nous verrons le but de cette commande
dans le chapitre 7 ;
• -t et - i , la plupart du temps combinés, qui permettent d'ouvrir un pseudo
terminal sur le conteneur. Ceci permet donc de travailler avec le conteneur en
mode interactif. Par exemple :
.. ..
6.4 INTERACTIONS AVEC UN CONTENEUR DEMARRE
Les diverses commandes de ce paragraphe permettent d'interagir avec un conten eur
démarré.
$ docker r un -d -- name l oop php php -r "whi l e( t r uel lec ho \ "Log somet hi ng every
1 2 sec\n\ " ; sl eep(2) ; }"
Elle n 'est certes pas très élégante, ma is compréh ensible :
• la commande ru n va c réer pu is démarrer un conteneur ;
• ce conten eur est créé à partir de l'image de base ph p 1 ;
l. [Link] [Link]/_/php/
6.4 Interactions avec un conteneur démarré -------------------El
La commande l ogs admet deux optio ns utiles:
• - - f o11ow ou - f permet de fonctionner en mode ta i l - f en affichan t les logs en
continu (au fur et à mesure qu'ils sont produits) ;
• - -t a i l Xperme t d'afficher X lignes de logs en partant de la fin.
Notez qu'il est possible de ch anger le pilote de logs (logs driver) d'un conteneur.
Docker en supporte nat ivement plusieurs et notamment des pilo tes comme fluentd 1
qui perme ttent de me ttre en place des systèmes de collecte, de centralisation et
d'indexat ion des logs.
Voyons ici un exemple dans lequel nous remplaçons le pilote par défaut par syslog
(le log système de Linux) :
$docker run -d -- l og -driver sys l og -- name loop php php - r "wh i le(true)(ec ho
1 \ "Log somet hi ng every 2 sec\n\ "; sl eep(2) ; }"
La commande exit met fin à l'exécution du termina l et rend la main sans pour
autant affecter le conteneur qui continue son exécution.
Il est évidemment possible de lan cer des commandes san s les modificateurs - i et
-t qui seront alors exécutées mode n on interactif.
Cette commande, comme son nom l'indique, permet de renommer un conten eur.
6.4 Interactions avec un conteneur démarré -------------------11391
6.4.5 docker cp
U ne fois le conte neur ouvert, l' inv ite du terminal bash est affichée. O uvrez un
nouveau terminal et entrez la commande suivante :
1 $ docker di ff exempl e
Même si vous attendez longtemps, rien ne s'affiche car le conteneur n'a subi aucune
mod ification par rapport à son image de base.
Revenons à notre premier terminal et entrez la ligne suivante :
$ docker di f f exempl e
1 A /test . txt
Nous pouvons constater que l'ajout du fich ier [Link] a bien été détecté.
À noter que la commande accepte aussi les mêmes options de configuration des
ressources que pour les commandes r un ou crea t e.
Nous avons déjà utilisé cette commande dans le chapitre 5. C elle-ci permet de
créer une image à partir d'un conteneur démarré.
N ous avons utilisé cette commande dans le chapitre 1 pour expliquer la structure
en couches des images Docker. Elle permet en effet de visualiser les différentes couches
d'une image et , e n regard, les instructions du Dockerfile qui ont été utilisées pour les
produire.
l:J
0 docker images COPTIONSJ CREPOSITORYC:TAGll
c
::J
0
\.0
.-t Cette commande permet de lister les images du cache local. Le paramètre - a
0
N permet de visualiser toutes les images intermédiaires (les couches) qui, par défaut, ne
@ sont pas visibles. Il est aussi possible d'appliquer des filtres via le paramètre - - f i l te r .
.......
..c:
O'l
·;::
>-
0..
0
6.5.5 docker rmi
u
docker rmi COPTIONSJ IMAGE CIMAGE...l
Ces deux commandes permettent d'importer des images depuis le cache local
Docker ou de les exporter vers le cache local. Elles permettent donc de transférer des
images entre hôtes sans faire appel à un registry :
"'Cl
0 Cette commande fonctionne avec la commande export. Elle permet d'importer le
c ~
,.,
0
:::i
"O système de fichiers d'un conteneur (préalablement exporté) en tant qu'image. À ce
[Link];
\.0 titre, son but est assez proche de celui de la commande commit.
.-t ~
0 V
N V
'ii
@ ·c
....... [Link];
..c
O'l
CO
c
0
6.6 INTERACTIONS AVEC LE REGISTRY
ï::::: c
>-
o. c
u
0 ·3ù Les commandes de cette section sont consacrées aux interactions entre le Docker
:::;
"O
0
.... Engine d'un hôte et les registries qu'il s'agisse du Docker Hub ou d'un autre registry
c.
~ public ou privé.
~
:::;
rS
"O
1
Notons que Google ([Link] et Amazon
0
c ([Link] ont annoncé la création de leurs propres offres de
8 registry de conteneur.
(Ç)
J 144, ___________________ Chapitre 6. Prise en main du client Docker
C ette commande permet d'importer une image du cach e local dan s un registry.
l:J
0 La commande pu 11 permet de téléch arger une image dans le cach e local de l'h ôte.
c
:J
0 N otons que cette commande est par défaut implicitement lancée par run ou create
\.0
.-t lorsque l'image utilisée n 'est pas présente dan s le cach e local.
0
N
@
....... Il est possible d'utiliser le nom de l'image ou le digest, un identifiant globalement
..c:
O'l
·;::
unique et non mutable.
>-
0..
0
u
6.6.5 docker search
C ette commande permet de recherch er dans un registry. La rech erch e se fait sur le
nom de l'image. Il est possible d'appliquer un filtre sur le n ombre d'étoiles attribuées à
l'image à l'a ide du paramètre - s.
6.7 Réseau et volumes --------------------------11451
$ docker search -s=3 redmi ne
NAME DESCR IPTION
STARS OFFI CIAL AUTOMATED
sameersbn/redmi ne 194
[O K]
redmine Redmi ne i s a flexib l e proj ect management w.. . 176
[ OK]
bi tn ami /redmi ne Bi tnami Docker Image for Redmi ne 7
[ OK]
74t h/redmi ne-al l -i n-one Redmine i nc l udes host in g SV N & Git. ba ckl. .. 3
[O K]
Cette commande permet de créer un nom alternatif pour une image. Par exemple
si vous d isposez de l'image « monimage » en version 1. 7, il est possible de créer un
alias alternatif pour cette image avec la commande suivante :
Ceci permet notamment de s'assurer que l'alias latest (couramment utilisé pour des
images Docker) po inte toujours vers la version la plus récen te d'une image.
l:J
0
0
c
::J ..
\.0
.-t
6.7 RESEAU ET VOLUMES
0
N
@ C es commandes sont apparues avec Docker 1.9 et apportent deux avancées majeures :
.......
..c: • le nouveau modèle réseau Docker dont nous allons parler en détail dans les
O'l
·;::
>- ch apitres 9 et 11 ;
0..
0
u • les volumes nommés qui permettent de s'affranch ir de la technique des data
containers dont nous verrons des exemples dans les chapitres 9 et 10.
C omme ces commandes seront abordées en détail dans la suite de cet ouvrage,
nous n'en ferons ici qu'une présen tation sommaire.
J 1461 - - - - - - - - - - - - - - - - - - - - Chapitre 6. Prise en main du client Docker
Commande Objet
docker network create Permet de créer un réseau Docker. Cette commande prend
notamment en paramètre - -driv er qui permet de spécifier le
type de réseau souhaité (par défaut bridge).
docker network connect Cette commande permet de connecter un conteneur à un
réseau.
docker network disconnect Cette commande permet de déconnecter un conteneur d'un
réseau.
docker network inspect Une fonction d'inspection du réseau dont nous verrons l'utilité
dans le chapitre 9.
docker network ls Une commande qui liste les réseaux disponibles. Par défaut, trois
réseaux sont systématiquement définis : none, hast et bridge.
docker network rm La commande qui permet de détruire des réseaux existants
(sauf évidemment nos trois réseaux prédéfinis).
Ce chapitre a pour but de décrire les instructions d'un fichier Dockerfile, leurs
paramètres et leurs particularités, et comment elles doivent être utilisées en pratique.
La première section introduira la façon d'écrire u ne instruction , appelée modèle,
puis la deux ième section détaillera les instructions principales. Les instructions plus
techniques seront étudiées dans le chapitre 8 .
..
7 .1 LES MODELES D'INSTRUCTION
7.1 .1 Introduction
l:J
0 U n modèle d 'instruction Dockerfile décrit simplement comment cette dernière doit
c
::J
~
.
.,
0 "O être utilisée. O n peut le comparer à la signature d'une méthode dans un langage
c::;
\.0 de programmation. A insi, pour chaque instruction, il existe au mo ins un modèle,
.-t
0
.,.,
~
N mais plusieurs sont souvent disponibles, chaque modèle couvrant un cas d'ut ilisation
·~
@ ·c spécifique.
....... B::;
..c: CO
Ol
0
c De manière générale, les modèles d'instruction sont simples à comprendre. Il
ï:::: c
>- c existe pourtant une particularité : certaines instructions (par exemple C MD ou
o..
u
0 ·3
<.) EN TRYPO INT) contiennent plusieurs modèles dont le résultat peut sembler similaire,
::;
"O
0
.....
c.
mais qui comportent quelques subtiles différences. C es modèles sont décrits par deux
~ formats particuliers : terminal et exécution. Nous nous attarderons sur ces deux formats
~
::;
afin de déterminer dans quels cas l'un ou l'autre do it être ut ilisé.
rS
1
"O
0
c
8
(Ç)
J 1481 - - - - - - - - - - - - - - - - - - - - - Chapitre 7. Les instructions Dockerfile
Notre exemple utilise le binaire pi ng, ce qui, au final, n'est pas un réel problème
s'il s'arrête brutalement ; par contre, si le processus en question est plus critique,
par exemple un serveur HTTP (Nginx, A pach e ... ), la situation serait différente : les
requêtes du serveur HTTP en attente de traitement ne seraient pas exécutées, ce qui
pourrait entraîne r des comportements étran ges au niveau des clients, ou pire, une
perte de données.
Vous souhaitez en savoir plus sur l'arrêt des conteneurs ? Un article décrivant
comment arrêter proprement un conteneur Docker et disponible v ia le lien ci,
dessous :
[Link]
@
'ii
·c tableau 7 .2 décrit les règles d 'utilisation des formats.
....... [Link];
..c CO
Tableau 7.2 - Règles d'utilisation des formats
O'l c
0
ï::::: c
>-
o. c Contexte d'utilisation Format
u
0 ·3ù
:::;
"O
Cas de tests terminal*
0
.... Commande se terminant directement après son exécution (par terminal*
c.
~
exemple : ls ou mkdir)
~
:::;
rS Commande lançant un processus (par exemple : ping ou httpd) exécution
"O
1
Autres cas exécution
0
c
8
(Ç) * pour autant que l'image cont ienne le bi naire /bin/sh , sinon exécuti on.
J 1501 - - - - - - - - - - - - - - - - - - - - - Chapitre 7. Les instructions Dockerfile
7.2.1 FROM
Image
l:J
0 Instruction FROM Autres instructions
c
::J
0
\.0
.-t
0
N
@
....... Image source
..c:
O'l
·;::
>-
0..
0
u
Figure 7.1 - Décomposition d'une image Docker
La figure 7.1 représente l'image résultante d'un Dockerfile. N ous pouvons con stater
que l'instruction FROM définit l'image source, et que les autres instruction s sont
exécutées à partir de cette image (installation d 'une applicat ion , exécution d'un
script ... ).
7.2 Les instructions d'u n Dockerfile ----------------------El
Le modèle de l'instruction FROM est:
FROM <image>[:<tag>l
<image> représente l'image Docker source. Cette image doit être disponible soit
localement, soit dans le Docker Hub ou dans votre registry privé.
<tag> représente la version de l'image Docker source. S'il n'est pas spécifié, alors
la dernière version (latest) est utilisée.
Par exemple :
FROM centos
1 FROM centos :7
FROM est la seule instruction obligatoire d'un [Link] ; de plus, elle doit être
placée en début de [Link] (précédée d'éventuels commentaires).
Un même [Link] peut contenir plusieurs fois l'instruction FROM afin de créer
plusieurs images. Prenons un exemple simple dont le but est de créer deux images : la
première affiche un message « Hello world » à son exécution et la deuxième« Bonjour
à tous ».
FROM centos :7
CMD echo "Hel l o world "
FROM centos : 7
1 CMD echo "Bonj our a to us "
$ docker bui l d .
Sending buil d cont ext t o Doc ker daemon 3. 072 kB
l:J
Step 1 : FROM centos :7
0
c ~
---> ce20c473cd8a
::J ,., Step 2 : CMD echo "Hello world "
"O
0
\.0
c::; ---> Run ni ng i n le0 94f 7bla01
.-t
0
.,.,
~ --- > cfef3a2f a477
N
'~
Removing i nt ermediate cont ainer le094f7b l a0 1
@ ·c Step 3 : FROM cent os : 7
B
.......
..c:
::;
CO --- > ce20c473cd8a
Ol
ï:::: 0
c Step 4 : CMD echo "Bonj our a t ou s"
c
>-
o.. c ---> Run ni ng in 07dc l 36e24b6
u
0 ·3
<.)
--- > 5b7f2d5028bd
::;
"O
0
Remov i ng i nt ermediate cont ai ner 07dcl36e24b6
.....
c. Successful ly bu ilt 5b7f2d5028bd
~
~
::;
rS Dans notre cas, la première image a pour identifiant cf e f3 a 2f a477 et la deuxième
"O
0
1
5b7f 2d5028bd.
c
8 Démarrons un conteneur avec la première image :
(Ç)
J 1521 - - - - - - - - - - - - - - - - - - - - - Chapitre 7. Les instructions Dockerfile
$ docker r un cfef3a2fa477
1 Hello worl d
Et maintenant un conteneur avec la deuxième image :
Un fichier Dockerfile doit contenir exactement une et une seule instruction FROM.
Pour conclure, reven ons sur l'utilisation du modèle sans spécifier la version de
l'image de base (le tag ), par exemple FROM centos. La probabilité que l'image ne
puisse pas être construite augmente avec le temps : pour rappel, en omettant la version ,
c'est la dernière qui est utilisée. Ainsi, entre la création in itiale du Dockerfile et la date
actuelle, la version de l'image source va très certainement évoluer. En reconstruisant
un Dockerfile dont la version de l'image source aurait ch an gé, notamment si une
n ouvelle version majeure a été publiée, alors les instructions suivantes peuvent ne plus
fon ctionner ; ça serait le cas, par exe mple, lors de l'installation d'un paquet existant
sur une ancienne distribution de Linux, mais plus disponible sur la version courante.
On peut donc retenir la règle suivante :
l:J
0
c Dans l'instruction FROM d'un fichier Dockerfile, il faut toujours spécifier la version de
:J
0 l'image source.
\.0
.-t
0
N
@ 7.2.2 MAINTAINER
.......
..c:
O'l
·;:: L'instruction MA IN TA IN ER permet de spécifier la personne en charge de maintenir
>-
0..
0 le Dockerfile, générale ment son auteur.
u
Le modèle est :
MAINTAINER <name>
<na me> est une chaîne de caractères représentan t l'auteur, par exemple son prénom
et son n om.
7.2 Les instructions d'un Dockerfile -----------------------8
Par exemple :
FROM centos :7
1 MA INTAI NER John Doe
Construisons et inspectons l'image :
7.2.3 RUN
L'instruction RUN (à ne pas confondre avec la commande docker run ) permet
d'exécuter des commandes utilisées généralement pour construire l'image. O n peut
représenter l'ensemble des instructions RUN comme l'écart entre l'image source et
l:J
l'image résultante.
0
c
::J
~
,., Il existe deux modèles pour l'instruction RUN :
"O
0 c::;
\.0
.-t
0
.,.,
~
RUN <command>
N
'~
@ ·c
....... B::;
..c: CO
Ol c
ï:::: 0
>- c
o.. c RUN ["executable", "param 1 ", "param2"l
u
0 ·3
<.)
::;
"O
0
.....
c. Le premier est orienté terminal et le second exécution.
~
~
::;
Par exemple :
rS
1
"O
0
c
8 RUN mkd i r /tmp/test
(Ç) 1 RUN [ "/bi n/sh ", "-c ", "mkd i r /tmp/test "J
J 1 s4I--------------------- Chapitre 7. Les instructions Dockerfile
Les instructions RUN servent à construire l'image ; ainsi, les commandes à exécuter
seront finies, c'est-à-dire inactives après leur exécution. Il est donc préférable d'utiliser
le format terminal qui est plus aisé à écrire et à comprendre.
Il est possible de combiner plusieurs commandes pour une même instruction RUN,
simplement en les séparant par des points-virgules (;) , par exemple :
Dépôt fictif
Imaginons à présent une image, appelée AB, avec un paquet A lpha en version 3
et un paquet Beta en version 2 ; cela signifie que lors de la construction de l'image ces
deux paquets étaient disponibles dans ces versions.
Image AB
l:J
0
c
::J
~
.
.,
"O
0 c::;
\.0
.-t
0
.,.,
~
Figure 7.3 - Dépôt fictif plus ancien
N
·~
@ ·c
....... B::;
..c:
Ol
CO
c À noter que seuls les paquets utiles à l'exemple sont représentés, tout autre élément
ï:::: 0
>- c de l'image étant volon tairement ignoré afin de faciliter la compréhension.
o.. c
u
0 ·3
<.) O n souhaite construire une image XYZ à jour dont l'image source est A B. O n écrit
::;
"O
0
.....
c.
alors naïvement le [Link] suivant :
~
~
::;
rS FROM AB
"O
0
c
1
1 RUN yu m upda t e -y
8
(Ç)
J 1561 - - - - - - - - - - - - - - - - - - - - - Chapitre 7. Les instructions Dockerfile
lmageXYZ
L'image XYZ contient donc logiquement le paquet Alpha en version 5, car il a été
mis à jour suite à la commande RUN y um upd ate -y.
Q uelque temps p lus tard, les paquets du dépôt fictif sont mis à jour ; de plus, un
nouveau paquet G amma est dispo nible, qui est dépendant du paquet Alph a dan s sa
derniè re version :
Dépôt fictif
r
Paquet Alpha Paquet Beta
Version 6 Version 3
r
î
Paquet Gamma
Version 1
l:J
0
c Figure 7.5 - Mise à jour du dépôt
::J
0
\.0
.-t
0
N
Nous souha itons ma inten ant ajouter le paquet Gamma à l' image XYZ, et nous
@ modifions donc le [Link] a insi :
.......
..c:
O'l
·;::
>- FROM AB
0..
0 RUN yum update -y
u 1 RUN yum i nstall -y gamma
Paquet Gamma
Version 1
lmageXYZ
Paquet Gamma
Version 1
l:J
0
c
::J
~
.
.,
"O
0 c::;
\.0 Figure 7. 7 - Seconde image : même Dockerfile, résultat différent
.-t
0
.,.,
~
N
·~
@ ·c
....... B::;
..c: CO
Ol c
ï:::: 0
c Conclusion
>- c
o..
u
0 ·3
<.) Lorsque nous souhaitons installer un paquet, il faut toujours s'assurer que les paquets
::;
"O
0
.....
existants sont à jour: n ous utilisons pour cela la commande yum upda te -y. Toutefois
c.
~ nous devons garantir que cette dernière est exécutée lors de chaque construction
~
::; impliquant l'installation d'un paquet supplémentaire. Ainsi, nous devons combiner
rS la commande yum update -y avec les yum inst al l -y nécessaires, si bien que nous
1
"O
0
c obtenons par exemple :
8
(Ç)
11581--------------------- Chapitre 7. Les instructions Dockerfile
7.2.4 CMD
L'instruction C MD permet d'exécuter une comman de (par exemple, une commande
U nix) au déma rrage du conteneur résultant.
Il est important de comprendre que cette instruction n 'est pas jouée lors de la
construction de l'image, mais bien lors de l'exécution d 'un conteneur associé. A insi,
son rô le est de fournir le contexte d'utilisation du conteneur, par exemple le démarrage
d'un serv ice.
CMD <command>
Le premier est orienté terminal et les autres exécution (sur le même principe que
l:J l'instruction RUN ).
0
c
::J Prenons un peu de temps pour décrire la troisième forme : nous constaton s
0
\.0 qu'aucun exécutable n'est spécifié, cela signifiant que l'instruction seule est incom~
.-t
0 plète ; elle do it don c être combinée avec l'instruction EN TRYPO INT (dont le
N
@ principe de fonctionnement sera donné dans la procha ine section) pour qu'elle
.......
..c: devienne fon ctionnelle. Illustrons la combinaison d'une instruction C MD avec une
O'l
·;:: instruction ENTRYPOIN T par un exemple :
>-
0..
0 Soit le Oockerfile suivan t :
u
FROM centos :7
ENTRYPOINT [" /bi n/pi ng ", "-c", "5"]
1 CMD [" l ocalhos t"J
N
'~ Pour surcharger l'instruction C MD, nous spécifions simplement la commande
@ ·c
....... B::;
comme paramètre d'exécution (un build préalable est bien sûr nécessaire) :
..c: CO
Ol c
1 $docker run my-ping -cmd ls
ï:::: 0
>- c
o.. c
u
0 ·3
<.)
::;
"O
0
.....
Ainsi pi ng l oc al ho s t sera remplacé par la commande l s (lister le contenu du
c.
~ répertoire courant).
~
::;
rS Continuons notre exemple avec le Dockerfile suivant:
1
"O
0
c
8 FROM centos : 7
(Ç) 1 ENTRY PO INT pi ng l ocal host
J 1601 - - - - - - - - - - - - - - - - - - - - Chapitre 7. Les instructions Dockerfile
La première constatation est qu'il est plus simple de surcharger une instruction
C MD que EN TRYPO INT; ainsi, nous privilégierons généralement cette façon de
fa ire. Ensuite, nous remarquons qu'il n'est pas toujours souhaité de surch arger la
totalité d'une commande. Dans ces derniers exemples, nous pourrions ne vouloir
surcharger que le nom de l'hôte (ici localhost) du pi ng et non toute la commande :
c'est dans ce sens que le cumul des instructions C MD et ENTRYPO INT devient utile.
Reprenons l'exemple my-ping : imaginons que nous souhaitons surch arger localhost
par "[Link]" ; l'exécution serait alors :
7.2.5 ENTRYPOINT
L'instruction ENT RYPO INT permet , tout comme l'instruction CMD, d'exécuter une
commande au démarrage du conteneur résultant.
l:J
0
c
:J
Elle possède les caractéristiques suivantes qui sont équivalentes à celles de l'ins-
0 truction CMD :
\.0
.-t
0
N
• ENTRYPOINT n'est pas jouée lors de la construction de l'image, mais lors du
@ démarrage du conteneur ;
.......
..c: • un Dockerfile peut contenir plusieurs instructions EN TRYPOINT, cependant
O'l
·;:: seule la dernière instruction du fichier sera exécutée.
>-
0..
0
u
Si un Dockerfile contient l'instruction ENTRYPOINT au format exécution et l'instruction
CMD (quel que soit son format), alors le contenu de l'instruction CMD (représentant
dans ce cas des paramètres) sera ajouté la fin de l'instruction ENTRYPOINT.
Si, par contre, un Dockerfile contient l'instruction ENTRYPOINT au format terminal et
l'instruction CMD (quel que soit son format>, alors l'instruction CMD sera ignorée.
Lors du démarrage du conteneur (doc ker run), il est possible de surcharger l'instruction
ENTRYPOINT grâce à l'option · · ent ry poi nt, par exem ple, docker run · ·ent rypoin t
ls my·app.
Format exécution
Prenons un exemple d'utilisation de l'instruction ENTRYPO INT au format exécution.
Soit le Dockerfile suivant :
FROMcentos :7
1 ENTRYPOINT ["ping "," google .com "]
Nous souhaitons maintenant affich er les conteneurs actifs afin de voir les corn,
mandes en cours (colonne COMMA ND du résultat).
$ docker ps
CONTAINER ID IMAG E COMMA ND CREATED
STATUS PORTS NAM ES
409d fc 57a7a6 pi ng-google -exec "pi ng goog l e . com " About a min ute aga
Up About a min ute t es t
Format terminal
Reprenons le même exemple, mais en utilisant le format terminal. Soit le Dockerfile
suivant:
FROM centos :7
l:J
0
c
1 ENTRYPOINT pi ng google . com
::J
0 N ous construisons ensuite l'image, puis nous démarrons un conteneur :
\.0
.-t
0
N
@ $ docker bu il d -t ping-goog l e-s he ll .
....... $ docker r un - -rm - -name test ping -googl e-shel l
..c:
O'l $ doc ke r ps
·;::
>- CONTAI NER ID IMAG E COMMA ND CREATED
0..
0 STATUS PORTS NAM ES
u c844052a05e9 pi ng-goog l e-shel l "/bi n/sh -c ' ping goo" 15 seconds aga
Up 14 seconds t es t
La commande en cours est cette fois,ci différente : I bi nI s h - c ' pi ng goo gl e . com '
Il s'agit du pi ng google . com, précédé par /b i n/sh -c. C 'est le fameux problème
d' encapsulat ion de l'exécution d'un bin aire (pin g dans notre cas) par un termin al
applicatif ( I bin I s h - c) lors de l'utilisation du format terminal. Vous trouverez plus
7.2 Les instructions d'un Dockerfile ----------------------11631
d'information à ce sujet dans la section « Terminal ou exécution ? », au début de ce
chapitre.
7.2.6 EXPOSE
L'instruction EXPOSE décrit les po rts du conteneur que ce dernier écoute. Un
port exposé n'est pas directement accessible, et il devra ensuite être mappé (soit
automatiquement, soit manuellement) avec un port de l'hôte exécutant le conteneur.
Hôte Ports
Conteneur Ports
30080
80
33306
d
Maria DB
3306
Par exemple :
1 EXPO SE 80 22
FROM centos :7
RUN yum update -y && yum i nst al l -y \
openssh -server \
passwd
RUN mkdir /var/run/ss hd
RUN ssh - keygen -t rsa - f /etc/ssh/ssh_host_rsa_key -N "
RUN user add user
RUN echo -e "pass\n pass " 1 (passwd --stdin user)
EXPOSE 22
CMD [" /usr/sbi n/sshd ", "- D"J
Pour finir, n ous construisons l'image (cette dernière sera utilisée ci-après) :
1 $ docker run -P -d ss h
L'option -d, quant à elle, permet d 'exécuter le conten eur en tâche de fond (ainsi
l'invite de commande reste disponible ). L'identifiant du conteneur est affich é.
Docker choisit un port aléatoire dans une plage. Cette dernière est définie à partir du
fichier /proc/sys/net/ipv4/ip_local_port_range.
$ docke r ps
CONTAI NER ID IMAGE COMMA ND CREATE D
STATUS PORTS NAMES
l d8e61685fe8 ssh "/usr/sbi n/sshd -D" 26 seco nds ago
Up 26 seconds 0. 0. 0. 0:32772 ->22/ t cp condescending_boot h
Dans le résultat ci~dessus, nous constatons que le port 3 277 2 de l'hôte est mappé
avec le port 22 du conteneur (ce dernier étant le port exposé).
Il est également possible d'utiliser la commande docker port <Ide nti fia nt du
con t ene ur > ; dans ce cas, nous obtenons le résultat suivant:
souhaite spécifier les ports hôtes à mapper, alors on est contraint de préciser également
quels sont les ports exposés correspondant, ce qui au final est logique.
L'option - p est cumulative, dans le sens où il est possible d'avoir plusieurs fois loption
- p pour la commande doc ker r un.
En résumé
l:J
0
c Soit nous utilisons l'option - Pet, dans ce cas, tous les ports exposés par l'instruction
:J
0 EXPOSE seront mappés automatiquement avec des ports disponibles de la machine
\.0
.-t hôte .
0
N
@ Soit nous utilisons l'option - p autant que nécessaire et, dans ce cas, les ports
.......
..c: exposés sont spécifiés manuellement ; l'instruction EXPOSE devient alors uniquement
O'l
·;:: informelle. Le mappage se fait soit automatiquement (on ne spécifie pas le port hôte,
>-
0.. par exemple - p 22) soit manuellement (on spécifie le port hôte, par exemple - p
0
u 35022 : 22 ).
Pour conclure cette section, reprenons une nouvelle fois l'exemple ssh: l'image a
été construite, le conteneur correspondant démarré et le port hôte est connu (dans
notre cas 35022), ce dernier étant mappé avec le port 22 du conteneur qui fait
référence au processus SSH. On souhaite maintenant se connecter au conteneur par
SSH avec l'utilisateur « user » et le mot de passe « pass » :
7.2 Les instructions d'un Dockerfile ----------------------11671
$ ss h user@l oca l host -p 35022
The authenticity of host ' [localho st J:350 22 ([::1 ] :35022)' can't be
established .
RSA key fi ngerprint is 09 : 7f :b6 : 6b :d5 :83 :3d:db :c5 : la :29 : f8: 7c : f6 :48 : l b.
Are you sure yo u wa nt to conti nue con nect i ng (yes/no) ? yes
Warning : Permanent l y added ' [loca l host ] :35022 ' ( RSA) to t he list of known
hosts .
user@l oca l host 's password :
[use r@ld8e61685f e8 ~ ]$
7.2.7 ADD
L'instruction A OD permet d'ajouter un fichier dan s l'image. La source du fichier
(d'où il provient) doit être disponible à travers la machine qui construira l'image (par
exemple , un fichier local ou distant si une connexion distante est possible ). Le fichier
sera définitivement ajouté dans l'image, dans le sens où il n e s'agira pas d'un raccourci
ou d 'un alias.
L'instruction ADD est très proche de l'instruction COPY, néanmoins il existe quelques
différences qui sont détaillées dans cette section et la suivante.
(celle qui exécute doc ker r un), simplement car l'ajout se fait à la construction de
l'image.
Par exemple:
En réalité, nous éviterons d'utiliser une source au format URL. En effet, la fonctionnalité
de téléchargement de l'instruction ADD est limitée : elle ne supporte pas les URL
protégées par un mécanisme d'authentification. Nous préférerons donc utiliser une
instruction RUN (par exemple, RUN wget... ou RUN curl..J à la place.
Le deuxième exemple prendra tout fi chier du dossier courant (de la machine qui
construit l'image) dont le modèle de nom correspond à« test* » (par exemple« testl »
ou « testlambda ») et les déposera dans le dossier « dossierRelatif/ » dont le chemin
est donné relativement (car il n'y a pas de slash en début de chemin) par rapport au
chemin courant dans le conteneur.
Pour finir, le troisième exemple prendra les fichiers testl et test2 (dans la machine
qui construit l'image) dont les chemins sont donnés spécifiquement (c'est-à-dire en
absolu) ; ils seront déposés dans le dossier « /dossierAbsolu/ » qui lui aussi est donné
spécifiquement.
Le dossier courant, ou plutôt le chemin courant de la machine qui construit
l'image, correspond simplement au chemin spécifié qui est donné en paramètre de la
commande docker build (le fameux « . » en fin de commande).
Lors de la construction d'une image, le chemin courant dans le conteneur est « / »,
l:J
à moins qu'il n'ait été changé par une instruction WORKDIR (voir chapitre 8 ).
0
c Afin de bien comprendre le principe du chemin courant dans le conteneur, prenons
::J
0
\.0
un exemple complet.
.-t
0
N Soit le Dockerfile suivant :
@
.......
..c:
O'l FROM centos :7
·;::
>- RUN pwd > /tmp/i nitialPath
0..
0 RUN mkdi r out put
u RUN cd out put
RUN pwd > /tmp/pat hAfterOutp ut
AOD t es tl . I
AOD [ "t est2" , "/out put / "]
CMO l s /output
Nous con sidérons que les fichiers testl et test2 existent et sont dans le même
dossier que le Dockerfile.
7.2 Les instructions d'u n Dockerfile -----------------------11691
Les instructions de type RUN pwd > file n ous permettent de sauvegarder le chemin
courant dans des fichiers que n ous déposon s dan s le dossier /tmp du con teneur.
L'instruction CMD ls /output nous permet , quant à elle, de lister les fichiers et
dossiers dans le dossie r /output au démarrage du conteneur.
Nous con struisons l'image :
Le résultat est :
1 test2
N ous voyon s logiquement le [Link] ier test2 qui a été déposé par l'instruction A OD
["test2" , 11 /output/'1]. Étant donné les instruction s RUN cd output puis AOD testl
./, nous pourrions cependant nous attendre à ce que le fi.c hier testl soit aussi dan s
le dossie r out pu t, car l'instruction A OD utilise le ch emin relatif « ./ » et, selon
l'instruction RUN, n ous pounion s pen ser être dan s le dossier output ... M ais ce n 'est
pas le cas : rappelons-nous que ch aque instruction dans un Dockerfile est exécutée de
manière indépendante dans le but de créer des images intermédiaires pour le système
de cach e. Ainsi, à ch aque instruction le contexte courant redevient celui par défaut
(dans notre cas « / » ), et notre [Link] testl se trouve donc à la racine. En démarrant à
nouveau le conteneur, mais en surch argeant le point d 'entrée par un ls / :
N
'~
@ ·c
....... B::;
$ docker run -- rm add cat / t mp/ i nitialPa t h
..c: CO
I
Ol c
ï:::: 0
c $ docker run -- rm add cat /tmp/pathAfterOutput
>-
o..
0
c
·3
1I
u <.)
::;
"O
0
..... Dan s les deux cas, no us con statons bien que le ch emin courant est « / ».
c.
~
~ M a is alors, si le dossier courant dan s le conten eur est toujours « / » , quelle est la
::;
rS différen ce entre un chemin absolu et un ch emin relatif ? En réalité, le dossier courant
1
"O
0
du conten eur n 'est pas toujours « / » ; il peut se paramétrer grâce à l'instruction
c
WORKDIR, et c'est dan s ce cas qu'il existe une différen ce entre un ch emin absolu et
8
(Ç) un ch emin relatif.
J 1101 - - - - - - - - - - - - - - - - - - - - - Chapitre 7. Les instructions Dockerfile
Maintenant que n ous avons bien compris comment fon ctionnent les ch emins
à spécifier dans l'instruction AOD, regardons la différence entre les deux modèles :
le premier (AOD <src> ... <<lest > ) est p lus facile à lire, ma is le deuxième (AOD
["<src>" ,... "<<lest >"]) permet d'ajouter des espaces dans les chemins san s devoir les
échapper. Dans la mesure où la bonne pratique d'écriture des noms de fichiers et de
dossiers consiste à éviter les espaces, nous préférerons utiliser la première forme.
Lorsque la source est un fichier défini par une URL, il ne sera pas décompressé, et ce
même s'il correspond à une archive de format reconnu.
FROM centos : 7
AOD word press- 4. 4. 1- f r_FR. tar . gz /tmp /
1 CMD l s /tmp
N ous constatons aisément qu'il s'agit bien de l'archive qui a été décompressée, car
elle contient des fichiers et des dossiers du CMS WordPress.
À première vue, il s'agit d'une fonctionnalité utile, et pourtant elle constitue deux
désavan tages majeurs :
7.2 Les instructions d'un Dockerfile ----------------------El
l , Tout fichier tar compatible sera décompressé. Si nous souhaitons simplement
ajouter une archive tar sans la décompresser, cela n'est pas possible (sauf en
utilisant un format source de type URL).
2. Il n'est pas toujours aisé de savoir si le format de compression est compatible
avec la décompression automatique. Nous pouvons donc penser qu'un fichier
sera décompressé, alors que cela ne sera pas le cas.
Dans le premier AOD, le fichier testl sera déposé dans le dossier /tmp du conteneur
avec pour nouveau no m outputl.
Dans le second ADD, le fichier test2 sera déposé dans le dossier /tmp/output2 et
gardera son nom.
l:J
0
c ~
,.,
0
::J
"O 7.2.8 COPY
c::;
\.0
.-t
0
.,.,
~
L'instruction COPY permet d'ajouter un fichier dans l'image. La source du fichier
N
'~
@ ·c (d'où il provient) do it être un fichier local à la machine qui construira l'image. Le
B
.......
..c:
::;
CO
fichier sera définitivement ajouté dans l'image, dans le sens où il ne s'agira pas d'un
Ol c raccourci ou d 'un alias.
ï:::: 0
>- c
o.. c
0 ·3 L'instruction COPY est très proche de l'instruction ADD, car elle compose avec
u <.)
::;
"O
0
les mêmes propriétés suivantes (voir la section précédente pour plus de détails) :
.....
c.
~ • le principe des chemins courants dans la machine construisant l'image et dans
~
::;
le conteneur ;
rS
"O
1
• l'utilisation de la fonction Match du langage Go pour l'interprétation des
0
c caractères géné riques ;
8
(Ç) • l'interprétation du slash optionnel à la fin de la destination.
J 1121 - - - - - - - - - - - - - - - - - - - - - Chapitre 7. Les instructions Dockerfile
<src> désigne le chemin local du fichier à ajouter à l'image. <s r c> peut être répété
autant de fo is que souhaité et peut contenir des caractères génériques (par exemple
« * »).
<ds t > désigne le chemin de destination du ou des fichiers à ajouter dans l'image.
Par exemple :
l:J Comme cela est mentionné dans la précédente section, nous utiliserons systémati-
0
c
:J quement l'instruction COPY (et non ADD>, notamment pour éviter les problèmes de
0
\.0
décompression automatique.
.-t
0
N
@
.......
L'instruction COPY, tout comme l'instruction A DD, pe rme t d 'ajouter plusieurs
..c: fichiers dans l'image, d'un seul coup. Pourtant, cette pratique n'est pas recommandée,
O'l
·;::
>-
0..
afin de pouvoir explo iter au mieux le cache Docker.
0
u Avant d'illustrer cela par un exemple, regardons tout d'abord comment fonctionne
le cach e avec les instructions AOD et COPY; le principe est simple : si au moins un
fi chier source est modifié (c'est-à-dire que son contenu est modifié ), alors l'instruction
sera considérée comme changée et sera donc rejouée (pas de cache ut ilisé), ainsi que
toute instruction suivante (principe général du cache Docker).
Voyons maintenant un exemple. Soit les deux Dockerfile suivants :
7.2 Les instructions d'u n Dockerfile ----------------------El
#Dockerfil e mult icopy l
FROM cent os :7
CO PY test l . t ar . gz /tmp/
RUN t ar xz f /tmp/testl . tar . gz
CO PY test2 . t ar .gz /tmp/
RUN t ar xz f /tmp/test2 . tar . gz
#Dockerfi le multicopy2
FROM centos :7
CO PY t es t l . t ar . gz tes t2 . t ar .gz / t mp/
RUN tar xzf /tmp/ t es t l . ta r . gz
RUN t ar xz f /tmp/test2 .tar . gz
Dans les deux cas, la construction n'utilise pas le cache Docker car il s'agit de la
première tentative.
Modifions les fichiers [Link] (pour chaque Dockerfile ) et reconstruisons les
images:
7.2.9 VOLUME
Hôte
Conteneur
data
l
i
.......
/var/home/vagranU ·
Par exemple :
VO LUME / tmp /d at a
1 VOLUM E [ "/ t mp/dat al", "/ tmp /data2" ]
Nous préférerons utiliser le modèle VOLUME <path> ... , ce dernier étant plus
lisible ; et pour limiter le nombre d'images intermédiaires, nous n'utiliserons qu'une
seule instruction VOLUME, avec au besoin plusieurs chemins, par exemple :
FROM centos: 7
VO LUME /tmp/data
1 CMD ping loca lhost
L'instruction CMD ping localhost permet de laisser le conteneur actif une fois qu'il
a démarré.
Nous construisons l'image, puis démarrons le conteneur:
Le dossier est vide. Faisons la même chose depuis l'hôte (à faire avec un utilisateur
root) :
1 $ docker exec vo l ume-cont eneur /bi n/sh -c 'echo "Hel lo " > / t mp/dat a/ hel l oîest'
A findes'assurer que la commandeecho "Hello " > /tmp/d at a/ hel loTest soitbien
exécutée en t ièrement dans le conteneur, on l'encapsule par terminal applicatif avec
/bin/sh ~c. En omettant ce procédé, la partie > /tmp / dat a/he l l oTes t serait exécutée
dans l'h ôte, ce qui n'est évidemmen t pas souhaité.
Listons une n ouvelle fois le volume :
Nous y voyons bien le [Link] helloTest fraîchement créé, quelle que soit la méthode
employée pour lister le volume. A rrêtons maintenant le conteneur :
1 $helsudo
l s /var/lib/doc ker/vol umes/ 4b l a5 .. . l lc55/_data
l oî est
Nous y voyons touj ours le [Link] h elloTest: le comportement attendu est bien
respecté. Toutefois, il serait utile que le chemin dans l'hôte soit plus explicite ; pour
cela, n ous utilisons l'option - v de doc ker ru n.
Tout d'abord, supprimons le conteneur afin de libérer l'espace utilisé par ce dernier
l:J et pour pouvoir réutiliser son nom :
0
c
::J
~
,.,
0
\.0
"O
c::; 1 $ docker rm volume -conteneur
.-t
0
.,.,
~
N
'~
·c
À noter que le volume dans l'h ôte est aussi supprimé. Ensuite, démarrons le
@
....... B::; conteneur avec l'option -v :
..c: CO
Ol c
ï:::: 0
>- c
o.. c $ do cke r run -d -v /va r / home/vagrant /data: /tmp/ data -- name volume-conteneu r
u
0 ·3
<.)
::;
"O
1 vol ume
0
.....
c.
~ /var/home/vagrant/data représente le ch emin dans l'hôte et /tmp/data le chemin
~
::; dans le conteneur. C réons à n ouveau un [Link] dans le volume ( rappelons~nous que
rS
1 la suppression du conteneur a également supprimé le volume ) :
"O
0
c
8
(Ç) 1 $ docker exec vo l ume -conteneu r /b i n/sh -c 'echo "Hello " > / t mp/da ta / hel l oTest'
Chapitre 7. Les instructions Dockerfile
Revenons sur la valeur de l'option ,v, notamment la partie qui décrit le point
de montage dans le conteneur, c'est~à~dire /tmp/data: nous remarquon s que cette
information fait double emplo i avec l'instruction VOLUME du Dockerfile. En réalité,
si nous spécifions l'option ~v sur un même volume défini par l'instruction VOLUME,
alors l'effet fonctionnel de cette dernière devient nul. Reprenons l'exemple :
• D'abord, nous arrêtons et supprimons le conteneur:
FROM centos :7
# VOLUME / t rnp/dat a
1 CMD pi ng l oca l host
7 .3 BONNES PRATIQUES
Pour conclure cette section, nous allons récapituler les bonnes pratiques de l'écriture
d'un fichier Dockerfile.
Généralités
Pour les instructions CMD et ENTRYPOINT, nous préférerons utiliser le format
exécution (par exemple CMD [11 ping11 , 11 localhost11 ]) afin d'assurer un arrêt propre d'un
conteneur.
Pour l'instruction RUN, nous préférerons utiliser le format terminal pour des
raisons de lisibilité.
Afin d'optimiser la gestion du cache Docker, nous trierons les instructions en
l:J
0
c fonction de la possibilité qu'elles soient modifiées dans le temps.
::J
0 L'ordre ci,dessous apporte un bon niveau fonctionnel et une bonne lisibilité. Nous
\.0
.-t
0
tâcherons de l'appliquer autant que possible :
N
@ 1. FROM
.......
..c:
O'l
2. MAINTAIN ER
·;::
>-
0.. 3. ARG
0
u 4. ENV, LABEL
5. VOLUME
6. RUN, COPY, WORKDIR
7. EXPOSE
8. USER
9. ONBUILD
10. CMD, ENTRYPOINT
J 1 sol--------------------- Chapitre 7. Les instructions Dockerfile
FROM
U n fichier Dockerfile contiendra une et une seule instruction FRO M , et nous
spécifierons aussi formellement la version (le tag ) de l'image source à utiliser, par
exemple FRO M centos:7.
RUN
Lo rs de l'installation de paquets avec l'instruction RUN, nous mettrons systéma~
tiquement à jour l'image courante et nous n 'utiliserons qu'une seule instruct ion,
c'est~à~dire :
CMD et ENTRYPOINT
Nous utiliserons en priorité l'instruction ENTRYPOINT (au format exécution, comme
mentionné ci~dessus) . L'instruction CMD sera utilisée si le point d'entrée do it être
surchargé partiellemen t (dans ce cas, l'instruction sera combinée avec EN TRYPO IN T)
ou complètement (dans ce cas l'instruction EN TRYPOIN T ne sera pas utilisée).
Un fichier Dockerfile ne contiendra au maximum qu'une seule instruction CMD
et ENTRYPO IN T.
EXPOSE
l:J
0
Bien que l'instruction EXPOSE ne soit utile que si nous spécifions l'option ,p au
c démarrage du conteneur, n ous n ous efforcerons de l'employer afin de renseigner
:J
0
\.0
clairement sur les ports (la nature des services) qu'utilise le conteneur.
.-t
0
N
@
ADDetCOPY
.......
..c: Nous utiliserons systématiquement l'instruction COPY au lieu de ADD, ceci afin
O'l
·;::
>- d 'éviter des comportements imprévisibles liés à la décompression automatique des
0..
0 archives tarde l'instruction A OD.
u
Nous préférerons utiliser le modèle COPY <src> ... <dest > (au lieu de COPY
["<src>" ,... "<dest >"]) car il est plus agréable à lire et à maintenir. Dans des cas
exceptionnels, o ù la bon ne pratique de l'écriture des n oms de fichiers et de dossiers
n 'est pas respectée, nous utiliserons l'autre forme.
N ous utiliserons une instruction C OPY par fichier à ajouter, ceci afin d 'optimiser
l'utilisation du cache Docker.
7.3 Bonnes pratiques ---------------------------El
VOLUME
Même si l'instruction VO LUME devait être surchargée lors du docke r run , nous nous
efforcerons de la mettre dans le Dockerfile afin de renseigner sur les points de montage
du contene ur.
Le chemin commencera toujours par un « / » afin d'éviter toute confusion ,
notamment si le Dockerfile contient des instructions WORKDIR.
Nous utiliserons une seule instruction VO LU ME avec le modèle VOLU ME
<path> ... et au besoin plusieurs chemins :
1 VOLUME /cheminl/dossier l \
/c hemi n2/doss i er2 \
l:J
0
c ~
1 ARG var i abl e
ENV var i abl e $( var i abl e: -valeur ParDéfaut l
::J ,.,
"O
0 c::;
\.0
.-t
0
.,.,
~
N
@
'~
·c En résumé
....... B::;
..c:
Ol
CO
c N ous avons décrit dans ce chapitre les principales instructions de Dockerfile. À
ï:::: 0
>- c travers différents exemples, nous avons abordé les principaux cas d'usage de ces
o.. c
u
0 ·3
<.)
commandes.
::;
"O
0
.....
Il est temps à présent d'aborder les commandes mo ins fréquentes et d'étudier quelques
c.
~ fonc tio nnalités plus avancées de Docker.
~
::;
rS
1
"O
0
c
8
(Ç)
"'O
0
c:
:::i
0
\.0
r-1
0
N
@
......,
..c:
en
·;::
>-
0..
0
u
8
Usage avancé de Docker
Nous avons vu dans les précédents chapitres comment installer Docker sur différents
environnements, comment créer des conteneurs, comment utiliser le client Docker
et comment créer des images à partir de Dockerfile.
L'objectif de ce chapitre est d'aborder des usages plus avancés de Docker.
Nous y décrirons quelques instructions Docke [Link] un peu mo ins courantes que celles
qui ont été présentées dans les chapitres précédents. Nous découvrirons ensuite
Notary, le système de signature d'images proposé par Docker. Enfin, nous verrons
comment installer un Docker registry privé.
Dans le p re mier exemple, nous constatons qu'il n'y a pas de signe « = »,et que la
valeur n'est pas encapsulée par des guillemets n i échappée (par exemple, un antislash
avant un espace). Dans le second exemple, les valeurs doivent être encapsulées par des
guillemets (par exemple, "James Bond") ou échappées (par exemple, Agent \ secret ),
un signe « = » devant également être présent entre le n om et la valeur.
1 $ docker run -- rm -- env myName="J ason Bourne " -- env myJo b="CIA " env
Cette dernière commande est un peu particulière : en effet, nous n'utilisons pas
echo $myJob, mais /bin/s h - c ' echo " $myJo b" '.La variable $myJob de la commande
echo $my Job sera substituée au niveau de l'hôte, ce qui correspondrait à echo "" (en
considérant que la variable n'existe pas dans l'hôte) ; à l'exécution, le résultat serait
donc vide au lieu d'afficher la valeur de la variable $myJob du conteneur. La version
/ bi n/ s h - c ' ech o "$my Job "', quant à elle, permet d'effectuer la substitution au ni veau
du conteneur (car echo est encapsulé par un terminal applicatif), de telle sorte que
nous obtenons le résultat souhaité.
Un autre cas typique d'utilisation de l'instruction ENV est la modification de la
variable d'environnement PATH. En effet, si un Dockerfile contient, par exemple,
l'installation d'une application ( RUN yum i ns t a11 ... ), il devient intéressant de
pouvoir y accéder facilement (c'est~à~dire en saisissant uniquement son nom et pas
son chemin absolu). Par exemple :
Pour exécuter un docker i nspect sur un conteneur, ce dernier doit être actif. Dans les
exemples ci-dessus, le conteneur n'est actif qu'un très court instant car il se termine
directement après l'instruction CMD qui est un simple echo. Pour prolonger l'activité
du conteneur, on pourrait surcharger la commande ec ho par un pi ng, ainsi le docker
run serait docker run - rm -name test env ping localhost.
["PATH=/ usr /local/sbin : / usr/ l oca l /bin : /us r/sbin : /us r /bin : /sbin : /bin "," myName=James
1 Bond","myJob=Agent secret"]
8.1.2 LABEL
L'instruction LA BEL permet d'ajouter des métadonnées à une image.
Le modèle est :
l:J
Les noms peuvent contenir lettres, chiffres, points (.), tirets ( ~) et soulignés (_). Ils
0
c peuvent être encapsulés par les guillemets ( 11 ) ou non.
::J
0
\.0
Les valeurs des labels doivent être encapsulées par des guillemets ( 11 ) . Si elles
.-t
0 contiennent un guillemet ou un retour à la ligne alors ces derniers doivent être préfixés
N
@
par un antislash , par exemple :
.......
..c:
O'l
ï::::
>-
LABEL app .descr i pt i on= "Voic i la description de \ "Mon app l ica t ion\ " \
u
0..
0 1 sur plusieurs l i gnes . "
Tout comme pour l'instruction ENV, les labels créés (ou modifiés) sont disponibles
dans toute la descendance de l'image. Autrement dit, un conteneur Docker a accès
aux labels décrits par son Dockerfile et ceux décrits par le Dockerfile de l'image source
(et ce de façon récursive).
Si le label existe déjà, alors l'instruction LABEL remplacera simplement la valeur
existante.
8. 1 Dock erfile: quelques instructions supplém entaires - - - - - - - - - - - - - - - - 1 l s1I
So it le Dockerfile suivant:
FROMcentos :7
LABE L app . name= "Mon app l i cation " \
"app . version" ="l. O" \
app .descri ption="V oic i l a desc r i pt i on de \ "Mon appl ica ti on\ " \
sur plu sieurs l ignes . "
CMD echo "fi n"
Tout s'est bien déroulé, toutefois les labels étant des métadonnées, on ne peut
rien constater à travers l'exécution d'un conteneur. O n peut cependan t utiliser la
commande do cker i ns pect sur l'image afin de lister les labels existan ts :
json .[Link] sign ifi e que nous affichons uniquement les labels, et ce au
format JSON. « test » représente le nom du conteneur actif.
Le résultat retourné est :
l "app .descri ption" : "Vo i ci l a description de \ "Mon applic ation\ " sur pl usieurs
l ignes ." , "ap p.n ame ":" Mon appl i cation" , "app. vers i on ": "l .O","buil d-date ":"2015-
1 12 -23 ", "l i cense ": "GP Lv2 ", "name ": "Cen t OS Base Image ", "vendor ": "Cent OS" l
Les labels build~date, license, name et vendor sont fournis par l'image source.
"'Cl
0
c:: ~
,., 8.1 .3 WORKDIR
:::i
"O
0 [Link];
\.0
.-t ~
L'instruction WORKDIR permet de changer le ch emin courant (appelé dossier de
0 V
N V travail) pour les instructions RUN, C MD, EN TRYPO IN T, COPY et A OD. Elle peut
'&
@ ·c être utilisée plusieurs fois dans un fichier Dockerfile. Son effet s'applique à toute
....... B
:::;
..c:: CO instruction qui suit .
O'l c
0
ï::::: c
>- c Son modèle est :
o..
u
0 ·3ù
:::;
"O
0
....
c. WORKDIR <chemin>
~
~
:::;
rS Par exemple :
1
"O
0
c
8
(Ç) 1 WORKDIR /tmp
Chapitre 8. Usage avancé de Docker
Dans cet exemple, le chemin courant sera changé en /tmp, cela signifian t que pour
toute instruction RUN, C MD, ENTRYPO INT, COPY et A DD impliquant un chemin
relatif dans l'image, ce dernie r sera pris à partir de /tmp.
FROM centos : 7
WORKDIR / t mp
WORKDIR test
1 CMD pwd
L'effet d 'un WORKDIR est appliqué en cascade aux images enfants. Voyons cela
par un exemple. Soit le Dockerfile suivant :
#Dockerfile workdirsource
FROM centos :7
WORKDIR /var
"'Cl
RUN pwd > /tmp /chemi nCouran t
0
c:: CMO cat / tmp /chemi nCourant
:::i
0
\.0
.-t Dans cet exemple, nous changeons le chemin courant en /var, puis on sauvegarde
0
N immédiatement la valeur retournée par la commande pwd dans un fichier cheminCou-
@ rant déposé dans /tmp. Si nous construisons et démarrons le conteneur, nous affichons
.......
..c:: le contenu de ce fichier, c'est-à-dire:
O'l
·;::
>-
0..
u
0
1 /va r
Si maintenant nous surchargeons le point d'entrée afin d'exécuter directement la
commande pwd dans le conteneur démarré, soit docker run - - rm workdi rsource pwd ,
nous obtenons exacte ment le même résultat :
1 /va r
8. 1 Dock erfile: quelques instructions supplém entaires ----------------11891
C e qui démontre bie n que l'effet de l'instruct ion WORKDIR s'applique à l'image
et donc aux conteneurs qui en découlent.
C ontinuons l'exemple avec un autre Dockerfile :
1 /var
C e qui démontre que l'effet d 'un WORKDIR s'applique bien aux enfants d'une
image.
De plus, l'effet de W ORKDIR /unChemin est équivalent à RUN cd /unChemi n &&
fai r eQuel queChose, mais l'utilisation de l'instruction WORKDIR offre deux avantages
non négligeables :
• tout d 'abord, un gain de lisibilité ; en effet , cela permet de voir directement la
véritable fonction d'un RUN ;
• ensuite, un gain en maintenabilité ; il suffit de changer une et une seule
instruction WORKDIR si nous décidons de modifier un chemin (un nom de
dossier, par exemple) impliqué dans plusieurs instructions RUN.
FROM cento :7
"'Cl
0 ENV chemi nCourant /tmp
c:: ~
,., WORKDIR $chemi nCourant/$unFi chier
0
:::i
\.0
"O
[Link]; 1 CMD pwd
.-t ~
0 V
N V
'&
Cet exemple produira /tmp/$unFichier comme résultat du pwd (au démarrage du
@ ·c
B conteneur). La variable $unFichier n 'existant pas dans le [Link], elle ne sera pas
....... :::;
..c:: CO
substituée, et ce même si le [Link] de l'image source con t ient une instruction du
O'l c
0
ï::::: c
>- c
genre EN V unFichier monFichier.
o..
u
0 ·3ù
:::;
"O
0
....
c. 8.1 .4 USER
~
~
:::;
Cinstruction USER permet de définir l'utilisateur qui exécute les commandes issues des
rS
"O
1 instructions RUN, CMD et ENTRYPOINT. Son effet s'applique à toute instruction
0
c qui suit et à toute image enfant.
8
(Ç) Le modèle est :
Chapitre 8. Usage avancé de Docker
USER<user>
1 USER httpd
La spécification d'un utilisateur avec l'instruction USER est surtout utile, et même
indispensable du point de vue de la sécurité, dans le cycle de vie d'un conteneur. Par
contre, lors de la construction de l'image elle-même, c'est-à-dire avec les instructions
RUN, nous garderons l'utilisateur root. Pour résumer:
• une image non-finale, c'est-à-dire une image qui sera principalement utilisée par
d'autres Dockerfile comme source, ne contiendra en général pas d'instruction
USER;
• pour une image finale, les instructions RUN seront effectuées en root (c'est-
à-dire avant toute instruction USER), puis on spécifiera un utilisateur afin
d'assurer que le processus actif du conteneur n'est pas exécuté en root.
FROM centos :7
RUN chown root : roo t /bi n/ t op && \
chmod 774 /bin / top
RUN groupadd -r mygroup && \
useradd - r -g mygroup my user
"'Cl
0 USER my user
c:: CMD /bin/top -b
:::i
0
\.0
.-t
0
Avec le premier RUN, nous nous assurons que le binaire /bi n/top (affichage des
N
processus en cours) appartient à l'utilisateur et groupe root et que seuls ces derniers
@
....... peuvent l'exécuter. Le deuxième RUN crée un utilisateur myuser, un group mygroup
..c::
O'l
·;:: et assigne l'utilisateur créé au groupe créé. L'option - b du binaire top définit que
>-
0.. ce dernier est exécuté en mode batch ; cela signifie que son exécution est toujours
0
u active avec un rafraîchissement régulier des processus en cours, jusqu'à ce qu'il soit
manuellement arrêté (dans notre cas, lors de l'arrêt du conteneur).
En construisant l'image et en démarrant le conteneur, nous obtenons :
$ docker bu i l d -t us er .
Send i ng build context to Docker daemon 2. 048 kB
1
8. 1 Dock erfile: quelques instructions supplém entaires -----------------El
Successful ly bu il t af7b2fa53d95
$ docker run --rm -- name user-con t eneur user
1 /bi n/sh : /b i n/to p: Permission denied
Étant donné que l'utilisateur courant est myuser (instruction U SER), n ous consta-
tons logiquement que le bina ire ! bi n/top n e peut être exécuté car seul root peut le
faire. Modifion s ma inten ant le Dockerfile :
FROM centos : 7
RUN chown root : root /bi n/top && \
chmod 774 /bin/top
RUN groupadd -r mygroup && \
useradd -r -g mygroup my user
RU N chown myuser :mygroup /bi n/to p
USER myuser
CMD /bi n/ t op -b
Repren on s [Link] ant l'exemple initial, et essayon s une autre approch e : n ous
allons autoriser les utilisateurs du groupe mygroup (soit l'utilisateur myuser) à exécuter
le bina ire /b i n/top comme super utilisateur (s ud o). N ous modifio ns le Dockerfile
ainsi:
FROM centos :7
RU N yum update -y && yum i nstall -y sudo
"'Cl
0
RUN chown root : roo t /bin/ t op && \
c::
:::i
~
,., chmod 774 /bin/top
0 "O
[Link]; RUN groupadd -r mygroup && \
\.0
.-t ~
useradd -r -g mygroup myuser
0
N
V
V
RU N echo '%myg roup ALL=NOPASSWD: / bin/top' >> /et c/sudoers
'& USER myuser
@ ·c
....... B
:::;
CMD sudo /bin/ t op -b
..c:: CO
O'l c
0
ï::::: c
>- c Le prem ier RU N va insta lle r le bina ire sudo (permettant la gestion de superu-
o..
u
0 ·3ù tilisateurs). Le dernier RUN va définir le groupe mygroup comme superutilisateur
:::;
"O
0
....
du bina ire / bi n/top, c'est-à-dire que tout membre pourra l'exécuter sans condition .
c.
~ Pour finir, n ous ajo utons sudo à l'instruction CMD pour dire que la commande sera
~
:::; exécutée v ia le binaire sud o.
rS
"O
1
Nous construisons l'image :
0
c
8
(Ç) 1 $ docker bui ld -t user .
Chapitre 8. Usage avancé de Docker
Alors que la configuration semble correcte, cela ne fonctionne pas : le système nous
dit qu'on doit avoir un tty pour faire fonctionner su do (car C entOS 7 est configuré
ainsi par défaut pour su do). tty est une commande permettant d'afficher le nom du
terminal associé à l'entrée standard : dans notre cas, il n'y en a pas. Pour résoudre notre
problème, nous avons deux solutions : soit modifier la configuration de CentOS 7 afin
qu'elle n'ait pas beso in de tty pour sudo, soit configurer un terminal pour l'entrée
standard. La deuxième solution é tant complexe, nous utiliserons la première :
FROM centos :7
RUN yum update -y && yum i nsta l l -y \
sudo
RUN sed -i -e 's/requi retty/ ! requ i retty/g' /etc/sudoers
RUN chown root :root /bin/top && \
chmod 774 / bi n/ top
RU N groupa dd -r mygroup && \
useradd -r -g mygroup myuser
RUN echo '%mygroup AL L=NOPASSW D: /bi n/ t op ' » /etc/ sudoe rs
USER myuse r
CMD sudo / bi n/to p -b
ARG <name>C=<defaultValue>J
8.1 Dockerfile: quelques instructions supplémentaires ----------------11931
<name > représente le nom de l'argument.
<de f aul tVa l ue> représente la valeur par défaut. Ce paramètre est optionnel, s'il
n'est pas spécifié et que lors de la construction de l'image l'argument correspondant
n'est pas donné en paramètre, alors sa valeur sera simplement vide.
Par exemple :
ARG var l
ARG var2="ma valeur "
1 ARG var3=4
Si la valeur contient des espaces, alors elle doit être encapsulée par des guillemets.
L'utilisation d'un argument défini par l'instruction ARG dans un Dockerfile se fait
de manière similaire à l'utilisation d'une variable d'environnement, c'est-à-dire :
Par exemple :
Dans le deuxième exemple, nous assignons une autre valeur à var2 si cette dernière
est v ide. S i sa création provenait de l'instruc tion ARG va r2= "ma va l eur ", alors va r2
ne serait jamais vide, et donc une autre valeur ne serait jamais assignée.
Il n'est possible d'utiliser un argument que s'il a été défini (par l'instruction ARG> avant.
Ainsi, nous veillerons à définir les arguments en début de Dockerfile.
"'Cl
0 C omme cela est mentionné plus haut, l'assignation des arguments définie par ARG
c:: ~
,.,
0
:::i
"O se fait lors de la construction de l'image, grâce à l'option - - bu i l d a rg qui fonctionne
[Link];
\.0 ainsi :
.-t ~
0 V
N V
'&
@
.......
..c::
·c
B
:::;
CO
1 -- build -arg <name>=<va l ue>
O'l c
0
ï::::: c
>- c Il est fortement déconseillé d'utiliser l'option - -bu i 1d-a rg pour passer des informations
o..
u
0 ·3ù sensibles, comme des clés secrètes ou des mots de passe, car les valeurs seront très
:::;
"O
0
.... probablement sauvées dans le cache des commandes exécutées dans le terminal.
c.
~
~
:::; Si nous souhaitons spécifier plusieurs arguments, alors n ous utiliserons plusieurs
rS
1 fois l'option , par exemple :
"O
0
c
8
(Ç) 1 $ docker build -- bui ld-arg var l=valeurl --bui ld -a rg var2="encore une valeur " .
Chapitre 8. Usage avancé de Docker
Les arguments donnés dans loption - - bui l d a rg doivent obligatoirement être définis
dans le Dockerfile. Si tel n'était pas le cas, une erreur serait retournée lors de la
construction de l'image.
FROM centos :7
ARG varl
ARG varZ="ma valeu r"
RUN echo $varl > / t mp/va r
RUN echo $var2 >> /tmp/var
CMD echo $varl
N ous constatons que la valeur de var 1 est vide dans le con teneur, ce qui est normal
car la portée des variables définies par ARG ne s'étend pas au conteneur. Modifions
l'instruction C MD par:
"'Cl
0
1 CMD cat / t mp/var
c::
:::i
0
\.0 C onstruisons et démarrons le conteneur une nouvelle fois :
.-t
0
N
@
.......
$ doc ker buil d --build-a rg var l=valeurl -t arg .
..c::
O'l
·;:: $ doc ker r un - -rm arg
>-
0.. va l eurl
0
u ma valeur
Cette fois~ci nous voyons bien les valeurs attendues pour varl et var2 car leur ajout
dans /tmp/var a été fait lors de la construct ion.
Essayons maintenant de surch arger la valeur de var 2 lors de la construction de
l'image :
8. 1 Dock erfile: quelques instructions supplém entaires -----------------11951
$docker bui l d - -bui ld -arg var l=valeurl -- buil d-arg var2="une autre va l eur " -t
arg .
FROM centos :7
ARG var=argument
ENV var vari abl e
RUN echo $var > / t mp/va r
CMD ca t / t mp/var
FROM centos :7
"'Cl
0 ENV var variab l e
c::
:::i
~
,., ARG var=argument
0 "O
[Link]; RUN echo Sv ar > / t mp/var
\.0
.-t ~
CMD ca t / t mp/var
0 V
N V
'&
@ ·c De no uveau, construisons l'image et démarrons le conteneur :
....... B
:::;
..c:: CO
O'l c
0
ï::::: c
>- c S docker bui l d -t arg
o..
u
0 ·3ù
:::; S docker run -- rm arg
"O
~
0
....
c. 1 variabl e
~
:::;
Le résultat est le même : $var vaut toujours « variable » . C e comportement est
rS
1 dû au fait que ENV prime sur ARG, quel que soit l'ordre des instruct ions; plus
"O
0
c précisément, le résultat sera le suivant :
8
(Ç) • si ENV est placé avant A RG : A RG sera ignoré ;
Chapitre 8. Usage avancé de Docker
• si ENV est placé après ARG : ARG sera valable jusqu'à ENV, puis, dès
l'instruction ENV, ARG sera remplacé.
Il n'est pas toujours évident d'identifier quels services utilisent telle ou telle variable
d'environnement; ainsi, l'utilisation de l'instruction ENV doit se faire avec précaution :
il convient de toujours vérifier que le nom d'une variable d'environnement que nous
souhaitons ajouter n'est pas déjà utilisé par un service dont l'application dépend.
Nous savons maintenant quelle instruction utiliser selon la portée souhaitée. Nous
avons également vu qu'il est possible de surcharger une variable d'environnement et
un argument. Toutefois, la surcharge se fait différemment :
• pour l'instruction ARG, la surcharge se fait logiquement lors de la construction
de l'image (docke r bui l d); en effet, cela n'aurait pas de sens de la faire lors du
"'Cl
démarrage d'un conteneur dans la mesure où un argument n'y est pas disponible ;
0
c::
:::i
• pour l'instruction ENV, la surcharge se fait lors du démarrage du conteneur
0 (doc ker run ), ce qui, dans certains cas, peut poser un problème de consistance :
\.0
.-t
0
imaginons une variable d'environnement utile lors de la construction d'une
N image, puis lors de l'exécution des conteneurs associés ; si l'on surcharge la
@
....... variable seulement lors du démarrage, alors nous aurons une valeur différente à
..c::
O'l la construction et à l'exécution.
ï:::::
>-
0..
0 La solution au problème de consistance de l'instruction ENV est représentée par
u
le cumul des instructio ns ARG et ENV. Voyons un exemple :
FROM cent os :7
ARG version
ENV vers i on ${version : -l .O}
RUN echo $version > / t mp/version
CMD ca t /tmp/vers i on
8.1 Dockerfile: quelques instructions supplémentaires -----------------11971
La valeur de la variable d'en vironnement est « ${version :- 1.0} », ce qui représente
la valeur de l'argument « version » s'il n'est pas vide, et « 1.0 » dans le cas contraire
(rappelons-nous qu'un argument placé avant une variable d'environnement est valable
jusqu'à cette dernière ).
Si l'argument « version » n'est pas surchargé lors de la construction de l'image, alors
ce dernier est vide et la variable d'environnement correspondante vaudra « 1.0 ».Et si
l'argument est surchargé, alors ce dernier n'est pas vide et la variable d'en vironnement
vaudra sa valeur.
Essayons le cas où l'argument « version » n'est pas surchargé :
$ run -- rm arg
1 1. 0
La variable d'environnement vaut bien « 1.0 ». Surchargeons maintenant l'argu-
ment avec « 1.2 » :
8.1.6 ONBUILD
L'instruction ONBUILD permet de définir des instructions qui seront exécutées
uniquement lors de la construction d'images enfants, ce qui signifie qu'elles ne seront
pas exécutées lors de la construction de l'image les contenant.
L'exécution des instructions ONBUILD n'est effectuée que dans les enfants directs.
Les éventuels enfants d'images enfants n'incluront pas ces instructions.
La figure 8.1 illustre l'emplacement où sont exécutées dans une image enfant
les commandes définies par des instructions ONBUILD dans une image source :
directement après l'instruction FRO M.
Le modèle de l'instruction O NBU ILD est :
ONBUILD <instruction>
-0
0
c:: <i ns tr uct i on> représente une instruction de construction (RUN, A OD, COPY,
:::i
0 USER et ARG).
\.0
.-t
0
Par exemple :
N
@
.......
..c:: ONBUI LD RUN mkd ir /tmp/test
Ol ONBUI LD COPY test* dossier Relatif/
ï:::::
>-
0..
0
1 ONBUI LD USER httpd
u
L'utilité de l'instruction ONBUILD n'est pas forcément évidente à comprendre,
et c'est pour cela que nous emploierons un exemple pratique pour illustrer un cas
d'utilisation réelle : il s'agira de construire une image permettant de compiler et
d'exécuter une application Python quelconque.
Pour commencer l'exemple, nous avons besoin d'une image source (appelée python-
app) capable de compiler et d'exécuter une application Python (dans notre cas, un
simple fichier .py) sans connaître cette dernière. N ous aurons le Dockerfile suivant:
#pyth on -app
FROM centos : 7
ONBU ILD ARG f ich ier="a pp . py"
ONBUILD COPY $f i chi er /a pp / ap p. py
ONBUILD RU N pyt hon -m py_compil e /a pp /a pp. py
ENTRYPOINT [ "python", "/ app / app . pyc "]
Les instructions ONBUILD vont copier un fichier Python (dont le nom par défaut
est [Link]) dans l'image et le compiler: le fichier Python dans l'image se nommera
dans tous les cas [Link].
Python est déjà présent dans l'image source CentOS 7, ainsi nous n'avons pas besoin
de le faire.
Comme cela est expliqué plus haut, les instructions ONBUILD ne sont jouées
que dans les images enfants; ainsi, l'argument fichier (défini par ARG) ne pourra,
si nécessaire, être surchargé que lors de la construction d'images enfants, ce qui
représente bien notre souhait dans la mesure où l'image source ne connaît pas
l'application Python.
L'instruction ONBUILD COPY $fichier /app/[Link] fera échouer la construction
de l'image enfant si le fichier décrit par l'argument « fichier » n'existe pas. Il n 'existe
pas de solution directe à ce problème, toutefois il convient de raguer avec le mot-clé
« onbuild »toute image incluant une ou plusieurs instructions ONBUILD. L'utilisateur
sera ainsi averti et devra prendre la peine de lire la documentation ou au moins le
"'Cl
0 Dockerfile de l'image source.
c::
:::i
~
,.,
0 "O
[Link]; Construisons maintenant l'image source en n'oubliant pas le tag « onbuild » dans
\.0
.-t ~ la version:
0 V
N V
'&
@ ·c
.......
..c::
B
:::;
CO
1 $ docke r build -t python-ap p: l .0-onbui l d .
O'l c
0
ï::::: c
>- c
o.. Nous avons maintenant notre image source python-app (en version 1.0-onbuild)
u
0 ·3ù
:::;
"O
permettant de compiler et d'exécuter un fichier Python dont le nom par défaut est
0
.... [Link].
c.
~
~
:::; Continuons l'exemple en exploitant l'image source python-app. Pour cela nous
rS avons besoin d'une application Python (qui sera appelée x2) : il s'agira d'un simple
1
"O
0
c programme dont le but est de multiplier une valeur (donnée en argument) par deux
8 et d'afficher le résultat. Voici son code :
(Ç)
J2ool Chapitre 8. Usage avancé de Docker
fi x2 . py
impo r t sys
x=int( sys .a rgv[ l ])
resu lt at=x*2
print (repr (x) +" * 2 = " +repr(resul ta t ) )
$ python x2 . py 5
15*2 = 10
"'Cl produira python / app / app. pyc 0 où 0 pourra être surchargé lors du démarrage du
0
c:: conteneur.
:::i
0
\.0
.-t
L'image source introduit un argument « fichier » dans les images enfants dont la
0
N
valeur par défaut vaut [Link]. Dans notre cas, l'application est définie par le fichier
@ [Link] (placé au même endroit que le Dockerfile), et on devra surcharger l'argument
.......
..c:: lors de la construction de l'image :
O'l
ï:::::
>-
u
0..
0 1 $ docker bu i l d -- build -arg fichier=x2. py -t python-x2
1 # Executi ng 3 bu i l d trigger s . ..
Cette ligne particulière est retournée uniquement lorsque l'image source con t ient
des instructions O N BU ILD : elle sert à attirer l'attention de l'utilisateur sur le fait que
des instructions qui ne son t pas dans le Dockerfile de l'image seront exécutées.
Pour terminer cette section, regardons ce qui se passe techniquement au niveau de
la construction d 'une image contenant une instruction ONBUILD :
1. À la lecture d'une instruction ONBUILD, le const ructeur Docker va créer
une mé tadonnée qu'il placera dans le manifeste de l'image au niveau de la clé
« OnBuild » . C ette mé tadonnée décrira l'instruction qui devra être exécutée
dans les images enfants. Il est possible de voir son contenu grâce à un docker
inspect sur l'image concernée. Par exemple, pour python ,app, nous obtenons :
$docker inspect - -format='{ {json .ContainerCon f ig .OnBuil d}} ' pytho n-app
[ "ARG fich i er=\ "app . py\ "", "COPY $fic hie r /a pp/app . py ", "RUN python -m
1 py_compile /ap p/app . py "J
2. Nous constatons bien que les trois instructions ONBUILD sont présentes dans
« O nBuild » .
STOPSIGNAL <signal>
<signa l > est le signal à utiliser. Il est représenté soit par un nombre définissant sa
position dans la table syscall, soit par son n om au format SIGNAME.
Tout signal, sauf SIGKILL et SIGTERM, peut être intercepté par un processus, ce qui
signifie que ce dernier le gérera comme il le souhaite.
Par exemple :
1 STOPSIGNAL 9
STOPSIGNAL SIGKI LL
Pour rappel, lors de l'arrêt d'un conteneur (docker stop), seul le processus de PID 1
est arrêté proprement par Docker ; c'est ce processus qui interprètera le sign al décrit
"'Cl par l'instructio n STOPSIGNAL (par défaut il s'agira de SIGTERM) . L'utilité de
0
c:: STOPSIGNAL est donc de changer ce signal et par conséquent le travail à accomplir
:::i
0 par le processus lors de l'arrêt du conteneur. À noter que le signal SIGKILL est
\.0
.-t également reçu par le processus après une certaine période (de 10 secondes par défaut)
0
N si ce dernier ne s'est pas terminé correctement.
@
.......
..c::
O'l
ï:::::
>-
..
0..
0
8.2 SECURISONS DOCKER
u
La sécurisation d'une architecture à base de conteneurs est un vaste sujet. Il existe
cependant deux cas d'usage relativement courants qu'il est ut ile de connaître :
• la sécurisation de la Docker Remote API avec SSL/TLS ;
• Docker Content Trust, le logiciel de la suite Docker dédié à la signature des
images.
8.2 Sécurisons Docker --------------------------12031
8.2.1 SSL/TLS pour la Remote API
L'API distante de Docker (en anglais Docker Remote API) a été présentée dans
le chapitre 3 de cet ouvrage. N ous allons rappeler ici brièvement comment elle
fonctionne et comment la configurer.
Le client Docker permet l'exécution des commandes Docker depuis un terminal.
Lorsqu'une commande est exécutée depuis le client, par exemple docker ps, une
requête HTTP REST correspondante est créée, en voyée et exécutée par le démon
Docker à travers un socke t. Le démon Docker expose donc toutes les commandes
Docker par le biais d'un socket. L'API Docker permet d'envoyer et d'exécuter des
requêtes au démon (via le socket) grâce à une interface REST /J SON.
Dans la configuration initiale du démon Docker, le socket par défaut est un socket
Unix localisé par /var/run/docke [Link]. A insi, en exposant ce socket U nix comme
un socket HTTP, on peut accéder à l'API. Regardons main tenant comment sécuriser
cette A PI. N ous allons pour cela devoir:
• créer une A utorité de certification (abrégé en C A en anglais) ; bien évidem-
ment, sur une véritable installation, nous utiliserions un certificat délivré par
une agence de certification ;
• créer et configurer un Certificate Signing Request (abrégé en C SR et traduit
par demande de signature de certificat) et une clé pour l' A PI de n otre démon
Docker;
• faire de même pour le client pour pouvoir ensuite interagir avec le démon
Docke r.
N ous utiliserons pour cela l'utilitaire opens s1 qui est disponible sur la plupart des
distributions Linux.
....
c. $ openss l genrsa -aes 256 -out ca - key . pem 4096
~
~
Generating RSA private key, 4096 bit long modulus ... . ...... . . .. . ...... . . ++
:::;
rS . . ...... . .. ..... .. .. .. . .... . . . ...... . .. ..... . . . ... ...... . . . . . . .... . ... . .. ++
1
"O
0 e is 65537 (0x10001)
c
8 Ent er pass phrase for ca -key . pem:
(Ç) Verifying - Enter pass phrase for ca - key .pem :
Chapitre 8. Usage avancé de Docker
Notez bien la pass phrase (phrase secrète) que vous utilisez. C'est le mot de passe
de votre clé et nous en aurons prochainement besoin.
Vous avez sûrement noté une commande étrange: echo 01 tee ca . srl. Elle
1
contient un numéro de série qui est incrémenté chaque fois que nous utilisons
notre clé pour signer un certificat.
$ openssl req -new -x509 -days 365 - key ca-key . pem -sha256 -out ca . pem
Enter pass phrase for ca -key .pem :
You are about to be asked to enter i nfo rmation that wi l l be incorporated
into your certi f i cat e request .
What you are about to enter i s what i s called a Distingu ished Name or a DN.
There are qui t e a few f i elds but you can leave some blank
For some fie l ds t he re wi l l be a de fau lt va lue,
If you enter '.' . t he fie l d wi ll be left bla nk.
1 openss l req -s ubj "/C N=SHOST" -sha256 -new -key server-key . pem -out [Link]
Il ne nous reste plus qu'à signer notre CSR pour générer le certificat de notre
serveur:
8.2 Sécurisons Docker l2osl
$ openssl x509 -req -days 365 -sha256 -i n server .cs r -CA ca . pem -CA key
ca -key .pem -out server -cert. pem
Si gna t ure ok
subj ect=/C N=l ocalhost . l oca l domai n
Getti ng CA Pr i va t e Key
Ent er pass phrase for ca -key . pem:
N ous avons maintenant tout ce qu'il nous faut pour sécuriser notre démon.
La procédure est identique à ce que nous avons déjà vu au chapitre 3 : il nous
faut éditer le fichier de configuration de Docker (disponible sous CentOS dan s le
fichier /usr/lib/systemd/system/[Link]) et adapter la ligne avec l'instruction
ExecStart:
$ sudo - i
$ vi / usr/li b/sys t emd/syst em/doc ker .se r vi ce
ExecSta r t =/ usr/bi n/docker daemon -H tcp : //0 .0.0.0:2376 ' -- t l sver i fy '
' - -tl scace rt=/home/vag rant /docke r -cert /ca . pem'
' -- tl scert =/ home/vagran t/docker -cer t/server -cert . pem'
' -- t lskey=/home/vag rant /docker -cert /server - key . pem' ...
$ exit
Il ne nous reste plus qu'à créer un certificat et une clé pour n otre client afin de
nous connecter sur notre démon Docker maintenant sécurisé.
$ openssl x509 - req -days 365 -sha256 -i n client. csr -CA ca . pem -CAkey
ca- key . pem -out cer t . pem -extf i l e extfi l e . cnf
Sign at ure ok
s ubject=/C N=c l ient
Getti ng CA Pri vate Key
Ent er pass phras e for ca-key . pem :
Il ne nous reste plus qu'à passer en paramètre à notre client Docker les différents
clés/certificats que nous venons de créer :
N'oubliez pas de remplacer $HOST par le nom de l'hôte sur lequel tourne le démon
Docker!
Docker nous signale effectivement que nous ne pouvons pas accéder au démon.
Nous disposons maintenant d'un démon totalement sécurisé. Heureusement, comme
nous l'avons vu au chapitre 4, des outils comme Docker Machine permettent d'automa-
tiser cette configuration standard qui est fastidieuse si on doit la réaliser manuellement.
1. h ttps://[Link] m/notary/
8.2 Sécurisons Docker --------------------------12011
1 $ export DOCKER_CONTENT_TRUST=l
C ette variable n 'est configurée que pour la session bash active. Si vous désirez
l'avo ir active en permanence, il vous faudra la définir de manière permanente pour
l'utilisateur, typiquement en la rajoutant dans votre-/ . bas hrc
FROM al pi ne :3.l
1 CMD pi ng loca l host
C onstruisons notre image en la taguant de telle façon que nous puissions ensuite
la pousser sur le Docker Hub. Nous devons pour cela spécifier le n om du dépôt
( dunoddocker) :
N ous avons maintenant une image prête à être poussée sur le Docker Hub. C'est à
"'Cl
0 partir d 'ici que les ch oses d iffèrent d'un push normal. Poussons notre image avec la
c::
:::i
~
,.,
0 "O commande standard docker push
[Link];
\.0
.-t ~
0 V
V
N
'& $ docker push dunoddocker/content_t rust :la t est
@ ·c
B The pus h refers to a r epos itory [docker. io/d unoddoc ker /content_t rust ]
....... :::;
..c:: 8f eüa3ef03d9 : Prepari ng
1
CO
O'l c
ï::::: 0
c unaut hori zed : au thenti cation requ i red
>- c
o..
u
0 ·3ù
:::;
"O
N ous avons effectivement oublié de nous identifier sur le Docker Hub. Utilisons la
0
....
c. commande docker login avant de pousser notre image :
~
~
:::;
rS $ docker logi n -u dunoddocker
1
"O
0
c
Pa ssword :
8 Log i n Succeeded
(Ç) 1 $ docker push dunoddocker/cont ent tr ust :l at es t
Chapitre 8. Usage avancé de Docker
Signi ng and pushing trust metadata You are about t o crea te a new root signing
key passphrase . Thi s passphrase wil l be used t o protect t he most sensi ti ve key
in your signing system . Pl ease choose a l ong , compl ex passphr ase and be
careful to kee p t he passwo rd and the key f ile i t self secure and backed up . It
i s hi ghl y recommended that you use a password ma nager t o generate the
passph rase and keep i t safe . There wi l l be no way to recover th i s key . You can
f ind t he key i n yo ur config di recto ry .
Ente r passphr ase for new root key wi t h ID b059adb :
Repeat passp hrase f or new root key wi t h ID b059adb :
Enter passphr ase for new repository key wi t h ID Ob06cba
(doc ker . io/dunoddocker/cont en t_trust) :
Repeat passp hrase f or new re posi tory key with ID Ob06cba
(docker . io/d unoddocker/content_trust) :
Fin i shed i ni tia l i zi ng "docker .i o/dunoddocker/cont en t_trus t"
Success f ully si gned "docker . io/ dunoddoc ke r/content_t r ust ":l atest
En effet, Docker Content Trust repose sur l'utilisation de deux clés distinctes :
• la clé de tagging : elle est générée pour chaque dépôt. Elle peut
facilement être partagée avec quiconque voudrait pouvoir signer
du contenu pour ce dépôt. Elle est stockée dans le répertoire
- / .docker/trust/private/tuf_keys/docker. io/<reponame> ;
• la clé offline : c'est la clé la plus importante car c'est la clé root. Il est donc
critique de bien la protéger, car au contraire des clés de tagging, il n'est
pas possible de la récupérer. On peut d'ailleurs la trouver dans le dossier
-/.docker/trust/private/root_keys.
En vérité, il y a même une troisième clé, dite de timestamp. Elle est stockée côté
serveur et permet de s'assurer de la fraîcheur de l'image.
"'Cl
0
c:: Ma intenant que nous avons une image sur le Docker Hub, tout utilisateur voulant
:::i
0 utiliser notre image aura la garantie que ce sera bien celle du publicateur (car « buildé »
\.0
.-t
0
par lui) . De plus, grâce au mécanisme de clé de timestamp, il aura aussi la garantie que
N ce sera la dernière image pour le tag.
@
....... Il y a cependant une contrainte à bien comprendre : si vous activez Docker Content
..c::
O'l
·;:: Trust et que vous désirez « puller » une image qui n'est pas signée, vous aurez un
>-
0..
0
message d'erreur du type :
u
Us in g defau lt t ag : lates t
Er ror : remote tr ust data does not exist for docker .i o/xxx /yyy :
1 notary .docker . io does not have tr us t data for docker . i o/xxx/yyy
L'astuce est de rajouter le paramètre --d i sable -content -tr ust à la commande
doc ker pu ll pour ignorer cette contrainte de manière ponctuelle.
8.3 Installer un registry privé ------------------------12091
Docker Content Trust est relativement récent (Docker 1.8), mais il répond à une
vraie attente : garantir l'intégrité des images, particulièrement lorsque celles-ci sont
distribuées via des réseaux non sécurisés tels qu'Internet. Toutes les images officielles
disponibles sur le Docker Hub sont d'ailleurs maintenant signées par Docker lnc .
..
8.3 INSTALLER UN REGISTRY PRIVE
Nous avons expliqué dans le chapitre 1 le principe de registry Docker. Nous avons
ensuite jusqu'ici (et nous le ferons encore dans les chapitres suivants) utilisé essentiel-
lement le registry public de Docker : le Docker Hub.
Cependant, nous avons aussi évoqué le fait qu'il était possible d'installer un registry
Docker privé. Dans cette section gui traite de cette fonctionnalité, nous utiliserons
l'image officielle Docker qui est disponible à l'adresse suivante : [Link]
corn/_}registry/
Pour ce faire, nous allons utiliser un conteneur qui va générer ces fichiers dans des
volumes qu'il nous suffira ensuite de brancher sur notre registry.
Pour créer le login/password, nous aurons besoin de l'utilitaire htpasswd qui
permet de générer une entrée cryptée dans un [Link], qui sera ensuite utilisé pour
l'authentification (en mode http basic). Cet utilitaire est disponible dans le repository
EPEL https-tools.
Pour la création des certificats, nous emploierons de nouveau l'utilitaire open s s1.
"'Cl
0
c ~
,., Voici le Dockerfile de notre conteneur de configuration :
:::i
"O
0 [Link];
\.0
.-t ~
0 V FROMcentos : 7
N V
'ii
@ ·c
B #I nst al l e l e reposi tory EPEL
....... :::;
..c CO RUN yum i nst al l -y -- seto pt =t sf l ag s=nodocs epel- rel ease && yum cl ean al l
O'l c
0
ï::::: c
>-
o. c #Inst al l e l es deux uti li taires do nt no us avons bes oi n
u
0 ·3ù RUN yum i nst al l -y -- setopt =t sfl ags=nodocs httpd -t ool s opens sl &&yum cl ean
:::;
"O
0 a11
....
c.
~
~ #Identi f i e deux vol umes desti nés a recevo i r l es f i chi ers
:::;
rS RUN mkd i r -p /opt /cert s
1 RUN mkd i r -p /opt/ aut h
"O
0
c VOLUME /opt/ cert s
8 VO LUM E /opt/aut h
(Ç)
Chapitre 8. Usage avancé de Docker
if!/bi n/bas h
ifCréa t ion du premier compte
echo "Creati on d'un compt e pour l ' uti 1i sat eur $REG_LOGIN "
htpasswd -Bbn $REG LOGIN $REGPASSWD > /opt/aut h/htpasswd
jfCréa t ion des certi f i cats
echo "Creati on des certif i cats SS L"
openss l req -new key rsa :4096 -nodes -sha256 - keyout /opt/certs/domain . key
-x509 -days 365 -out /opt /certs /domain . crt -subj ' /CN=l oca l host '
Nous allons maintenant créer deux volumes nommés qui vont recevoir les fichiers à
créer:
• un volume certs_volume qui va recevoir les clefs publiq ue et privée SSL ;
• un volume auth_volume qui recevra le fichier htpasswd contenant le
"'Cl
0
login/password encrypté.
c::
:::i
0 Voici les instructions requises :
\.0
.-t
0
N
@ $ docker volume create -- name=certs_vol ume
.......
..c::
1 $docker volume create --name=aut h_vol ume
O'l
ï:::::
>-
0..
Nous pouvons maintenant lancer notre conteneur avec la commande suivante:
0
u
$ docker r un -- rm -- env REG LOGIN=admi n -- env REG PASSWD=admin l234 -v
1 certs_volume : /opt/cert s -v auth_volume : /opt/auth regconfig
Voici quelques explications relatives à la ligne de commande ci-dessus :
• - - rm va faire en sorte que ce conteneur s'autodétruise après usage. Il s'agit
clairement d'un conteneur de type script ;
8.3 Installer un registry privé ------------------------El
• - -env spécifie les valeurs pour les deux variables d'environnement (REGLOGIN
et REGPASSWD) contenant respectivement le login et le mot de passe de notre
compte sur le registry ;
• nous associons les volumes nommés à des chemins du conteneur :
- certs_volume va être associé au chemin /opt/certs et il recevra les certificats
SSL générés par openssl,
auth_ volume va être associé au chemin /opt/auth et il contiendra le fichier
htpasswd.
S i vous regardez le fichier [Link] plus haut, vous verrez que les différents
fichiers sont bien créés dans les chemins qui pointent vers nos deux volumes.
Nous pouvons maintenant créer un conteneur pour aller vérifier que nos deux
volumes contiennent bien les fichiers dont nous avons besoin :
$ docker run --rm -t -i -v cert s_vo l ume : /opt /certs -v auth_vol ume : /opt/a ut h
centos : 7 /bi n/bas h
[root @42bda61680f6 /]# l s /opt/certs/
"'Cl
domain .crt doma i n. key
0 [root@42bda61680f6 /J# l s /opt/auth/
c:: ~
,.,
:::i
"O
htpasswd
0 [Link];
\.0
.-t ~
0
N
V
V C'est effectivement le cas !
'&
@ ·c
....... B
:::;
..c:: CO
O'l
ï:::::
c
0
c
8.3.3 Lancement du registry
>- c
o..
u
0 ·3ù La création de notre registry repose sur la commande suivante :
:::;
"O
0
....
c.
~
~ docker r un -d -p 5000 :5000 --restart=a lways - -name reg i stry \
:::;
rS -v aut h_volume : /a ut h \
1 -v certs_vol ume : /cert s \
"O
0
c -e "REGISTRY_AUTH=htpasswd " \
8 -e "REGISTRY_AUTH_HTPASSWD_REALM=Reg istry Rea l m" \
(Ç) -e REGIST RY_AUTH_HT PASSWD_PATH=/ auth/ht passwd \
Chapitre 8. Usage avancé de Docker
Vous noterez :
• que nous associons le volume au th_ volume (qui contient le fichier htpasswd)
au chemin /auth ;
• que nous associons le volume certs_volume (qui contient les deux clefs SSL
[Link] et [Link]) au chemin /certs.
Le registry va aller puiser dans ces deux chemins pour y trouver le login/password
et les certificats SSL.
Une fois le registry lancé, vérifions que nous pouvons nous y connecter:
Poussons, par exemple, notre image de script de configuration regconfig définie plus
haut dans notre nouveau registry.
Nous devons d'abord taguer notre image à l'aide de l'instruction suivante :
Nous pouvons vérifier que l'image est bien présente en utilisant curl pour interroger
l'API REST du registry (sans oublier le login/password) :
Le flag - k de curl est nécessaire car nos certificats SSL sont selfsigned. Ils seraient
donc rejetés par curl sans ce paramètre.
En résumé
Les trois chapitres de cette partie vous ont permis d'apprendre à fabriquer des images,
mais aussi à piloter le Docker Engine au travers de sa ligne de commande.
Il est maintenant temps d'aborder des exemples plus complexes mettant en jeu des
concepts plus pointus.
"'Cl
0
c::
:::i
0
\.0
.-t
0
N
@
.......
..c::
O'l
·;::
>-
0..
0
u
ï:J
0
c::
:::i
0
\.0
r-1
0
N
@
......,
..s:::::
Ol
·;:
>-
0..
0
u
-.
QUATRIEME PARTIE
Exemples
d'architectures et
concepts avancés
Cette dernière partie comprend trois chapitres qui sont autant d'exemples de mise en
œuvre d'architectures à base de conteneurs.
-0 Outre leur sujet propre, ces chapitres nous permettent aussi d'expliquer des
0
c:: concepts avancés que nous n'avons pas encore pu complètement aborder.
:::i
0
\.0 A insi cette partie comprend les chapitres suivants :
.-t
0
N • le chapitre 9 traite des architectures multi~conteneurs et nous permet d'aborder
@
.......
l'usage d'outils comme Supervisor, mais aussi de comprendre en détail la gestion
..c:: du réseau avec Docker (et plus spécifiquement du réseau de type bridge) ;
O'l
·;::
>-
0..
• le chapitre 10 montre comment utiliser Docker dans le cas d'un environnement
0
u de développement « intégration continue» . Il nous permet d'aborder l'usage
des conteneurs comme outils de déplo iement, mais aussi la notion de Docker
API, conteneur nécessaire pour utiliser Docker depuis un conteneur ;
• le chapitre 11 expose un exemple de mise en œuvre de la solution Docker
Swarm (que nous avons décrite dans le ch apitre 2). Il permet d'aborder le
dernier modèle de réseau Docker: le modèle overlay.
Chaque chapitre s'appuie sur des cas pratiques mettant en œuvre l'environnement
que vous avez créé dans le chapitre 3.
ï:J
0
c::
:::i
0
\.0
r-1
0
N
@
......,
..s:::::
Ol
·;:
>-
0..
0
u
9
Application multi-conteneurs
Tout au long de ce chapitre, nous allons travailler avec une application web basée
sur le fra mework PHP Symfony2 1. N ous aurons besoin pour cela :
"'Cl
0 • d'un serveur web. Nous utiliserons Nginx que vous avez déjà rencontré dans les
c
:::i chapitres 3 et 5 ;
0
\.0
.-t
• de PHP,fPM 2 pour exécuter notre application. PHP Fast Process Manager
0
N est une implémentation FastCGI PHP spécialement adaptée aux sites à forte
@ charge;
.......
..c
O'l
• et d'une base de données MariaDB3 pour la persistance .
'i:
>-
0.
0 Nous allons suivre plusieurs approches pour « dockeriser » notre application :
u
• tout d'abord, nous n'utiliserons qu'un conteneur et verrons rapidement les
limitations de ce modèle pour un environnement de production ;
• n ous répartirons ensuite nos différents moteurs d'exécution sur plusieurs conte,
neurs, afin de mettre en place une architecture de micro,services ;
1. [Link]
2. [Link]
3. [Link]
Chapitre 9. Application mufti-conteneurs
• nous terminerons ensu ite avec le meilleur des deux mondes en découvrant
Docker Compose 1.
/. localhosl
'-
NGUllX --
9000
-- Nil~""I ~
3306 M
#aoB
~ '~
4~ 80
-- ' ' ~
-- ...
........,
.;":.==·- --- ··· Volume Volume
-·-
l:l=-::.=--:;.. app bd
~ ~
1. [Link]
2. LEMP: Linux, Nginx, MySQL/MariaDB, PH P
9. 1 Un seul conteneur, plusieurs processus --------------------12191
données seront accessibles pour notre machine hôte et faciliteront le développement
de n otre application.
S i ce n 'est déjà fait, récupérez les fichiers nécessaires avec la commande suivante :
1 $gi t clone http s : //git hub. com/dunod-dock er/app l icat i on-mul ti-co nt eneurs . git
Tous les fichiers dont nous aurons besoin sont disponibles dans le réperto ire
supervisor. Nous allons décomposer petit à petit le Dockerfile qui va nous permettre
ensuite de créer l'image de notre futur conteneur.
Le Dockerfile que nous allons utiliser se trouve directement à la racine du réperto ire
superv isor. N otre image sera basée sur une distribution C entOS 7. Nous utiliserons
pour cela l'image officielle fournie par le Docker Hub:
1 FROM centos :7
N ous utilisons ensuite yum pour :
• installer le dépôt EPEL. Celui~ci nous permet d'obten ir des versions plus
récentes des différents programmes qu'en utilisant le dépôt standard de
C entOS;
• mettre à jour les paquets déjà présents sur notre image;
• installer Nginx, les différents paquets PHP nécessaires à Symfony dont PHP~
FPM, MariaDB (serveur et client) et finalement Supervisor. Nous verrons un
peu plus lo in ce qu'est Superv isor.
"'Cl
0
c::
:::i
~
,.,
0 "O # Dockerfile
[Link];
\.0 RUN yum i nst al l -y epel- releas e && \
.-t ~
0 V
V
yum updat e -y && \
N
'& yum i ns ta l l -y mariadb-server mariadb -client\
@ ·c
....... B
:::;
ngi nx \
..c::
O'l
CO
c
php -common php -cl i php -fpm php -mysq l php -apcu php -curl
ï::::: 0
c php-i nt 1 ph p-mb s tr i ng \
>- c superv i sor && \
o..
u
0 ·3ù yum cl ean al l
:::;
"O
0
....
c.
~
~
:::;
C ette façon d'écrire n otre Dockerfile suit les bonnes pratiques de Docker. Elle offre
rS un juste milieu entre lisibilité et nombre de couches pour notre image finale.
1
"O
0
c Maintenant que n ous avons installé nos moteurs d'exécution , il ne nous reste plus
8 qu'à les configurer. C ommençons tout d'abord par Nginx.
(Ç)
J22ol-------------------- Chapitre 9. Application mufti-conteneurs
9.1.2 Nginx
La façon dont Nginx et ses différents processus fonctionnen t est déterminée via des
fi chiers de configuration. Nous aurons besoin de deux fichiers :
• le fichier principal de configuration de Nginx. Par défaut, ce fichier qui se
nomme [Link], est présent dans le répertoire /etc/nginx/ sous C entOS 7 ;
• un fichier de configuratio n par site web, soit, dans notre cas, un fichier
symfony .conf qui contiendra la configuration Nginx propre à notre application .
Nous allons tout d'abord créer n otre propre fichier [Link] qui remplacera
ensuite celui créé lors de l'installation de N ginx :
worker_proc esses 2;
pi d /var/run/ng i nx . pid ;
event s { l
htt p {
sendfi l e on ;
def ault_type applicat i on/octet-st ream ;
i nc l ude /etc/ng i nx/mi me. t ypes;
i nc l ude /etc/ng i nx/si t es-enabled/* ;
access_log /var/log/nginx/access . log ;
error_l og /var/ log/ngi nx /error . l og;
1. [Link] nx
9. 1 Un seul conteneur, plusieurs processus - - - - - - - - - - - - - - - - - - - - 1221 I
f astcg i_split_pat h_i nfo -( .+\ . php)(/ .*)$;
i nclude f astcgi_params;
f astcgi_param SCR IPT_FI LENAME Srea lpa th_rootS f astcgi _script_name ;
f astcgi _param DOCUMENT_ROOT Srea l path_roo t;
Nos deux fichiers sont ensuite copiés dans notre image, dans les réperto ires
standards de configuration de Nginx, via les instructions COPY du Dockerfile. Il
ne nous reste plus qu'à rendre notre site disponible (en créant un lien symbolique de
notre [Link] [Link] du répertoire sites-enabled vers sites-available ) grâce à une
commande RUN et créer notre réperto ire racine :
1 date . timezone=Europe/Paris
Ensuite, nous devons créer un autre fichier [Link], propre à PHP-FPM,
qui contient la configuration du processus qui traitera les demandes transmises par
Nginx. À nouveau, nous n e décrivons ci-dessous que les parties intéressantes :
[ symfony]
user = apache
group = apache
• toute requête arrivant sur le port 9000 sera acceptée et traitée par ce pool de
connexion;
• nous définissons un fichier de log propre à notre application
(symfony_error.log) ;
• nous plaçons les fichiers de sessions qui seront créées par notre application dans
un réperto ire dédié.
1. Cet ut ilisateur, qui est créé par l'installation de PHP-FPM, est utilisé par défaut. Nous avons donc
choisi de le garder.
9.1 Un seul conteneur, plusieurs processus --------------------12231
#Ada ptati on de 11UID du user apac he
RUN usermod -u 1000 apache
Certains auront remarqué que nous n'avons pas expliqué la commande usermod -u
1000 apache. Il s'agit d'une modification indirectement imposée pour assurer une
communication correcte entre le conteneur et son hôte au travers des volumes.
Nous y reviendrons en temps voulu.
9.1.4 MariaDB
Il ne n ous reste plus qu'à exposer le port 80 de Nginx et à définir deux volumes :
• un pour le code de notre application (/var/www/) ;
-0
0
c • un pour nos données MariaDB (/var/lib/mysql) .
:::i
0
\.0
.-t
0
N EXPOS E 80
@ 1 VOLUME [" /va r / l ib/mysq l / ", "/var/www/ "J
.......
..c
O'l
ï::::: Voilà ! Nous avons nos trois programmes installés et configurés. Il ne nous reste
>-
0. plus qu'à ajouter une commande CMD (ou ENTRYPOINT). Mais laquelle? N ous
0
u allons nous h eurter à une limitation de Docker : un seul processus peut tourner en
mode foreground (bloquant) par conteneur.
Comment donc faire tourner nos serveurs Nginx, PHP~FPM et MariaDB?
Pour ce faire, il nous faut utiliser un gestionnaire de services : nous allons employer
Supervisor1.
1. h ttp://[Link]/
J224I-------------------- Chapitre 9. Application mufti-conteneurs
9.1.6 Supervisor
Supervisor (ou plus précisément son démon supervisord) est, comme son nom
l'indique, un superviseur de processus. C'est lui qui sera le processus bloquant unique
du conteneur (celui avec le PID 1). Il va devoir démarrer, puis contrôler tous les autres
processus à savoir Nginx, PHP~FPM et MariaDB.
Sa configuration est stockée dans le fichier [Link]:
[supervisord]
nodaemon=true
l ogfile=/var/ l og/supervisor/supervisord .l og
[ program :n ginx]
command=/usr/sb i n/nginx -g "daemon of f; "
autorest art=tr ue
[ program :mysq l J
command=/usr/bin/mysq l d_safe
Nous définissons dans les blocs [ program] les processus que Supervisor devra
gérer. Sans entrer dans les détails, le paramètre comma nd correspond à la commande
qui va lancer le processus fils. Notez qu'il est possible de demander à Supervisor de
redémarrer automatiquement un processus qui se serait arrêté avec la commande
autorestart=true.
Il ne nous reste plus qu'à copier ce fichier et à configurer notre conteneur pour ne
lancer que Supervisor au dé marrage, le laissant ensuite démarrer et gérer les autres
processus:
AOD supervis or /s uperv isord . conf / etc/s upe r vi sor/conf . d/superv isord . conf
"'Cl
0
c:: CMO [" / usr/ bin /supervis ord", · -n·. ·- c·.
0
:::i
\.0
1 "/etc/superv i sor /conf .d/superv iso [Link] nf "]
.-t
0
N
@ 9.1.7 Notre code source
.......
..c::
O'l
·;::
Nous avons maintenant une image totalement fonctionnelle. Avant de la fabriquer à
>-
0.. l'aide de la commande docker bu i l d, il nous reste une dernière ch ose à faire: créer
0
u sur notre machine de développement le répertoire qui sera utilisé comme volume.
Nous les créons simplement avec la commande:
Container lemp-symfony
/var/www/
Figure 9.2 - Gestion des droits des fichiers dans les volumes montés
Nous avons décidé de créer un volume entre notre hôte et notre invité afin de
pouvoir modifier le code source depuis l'extérieur du conteneur.
C'est là que la question de l'UID entre en jeu. Le nom de l'utilisateur importe peu,
mais il est essentiel que les deux utilisateurs, vagrant à l'extérieur et apache à l'intérieur
aient le même UID pour disposer des mêmes droits d'accès. Dans le cas contraire,
les fichiers édités par notre utilisateur vagrant seraient illisibles pour notre utilisateur
apache.
"'Cl
0
c:: ~
,., O r sur notre hôte, la commande suivante nous apprend que l'utilisateur vagrant est
:::i
0 "O
[Link]; associé à l'U ID 1000 :
\.0
.-t ~
0 V
N V
'& $ cat /etc/passwd ]grep vagra nt
@
.......
..c::
·c
B
:::;
CO
1 vagrant :x: lOOO : lOOO : : / home/vagrant : /bin/bash
O'l c
0
ï::::: c Par défaut, l'utilisateur apache créé par le processus PHP-FPM dans le conteneur
>- c
o..
0 ·3ù est associé à l'UID 48 :
u :::;
"O
0
....
c.
~ [root@93llce834a53 /J
~
:::; # cat /etc/passwd ] grep apache
rS 1 apache :x:48:48:Apache : / usr/share/ httpd : /sbin/nol ogin
1
"O
0
c
8 Ceci explique la raison pour laquelle nous lançons la commande suivante dans
(Ç) notre Dockerfi le :
J226I Chapitre 9. Application mufti-conteneurs
Celle-ci fait simplement en sorte que l'utilisateur apache puisse lire les fichiers
produits par notre utilisateur vagrant.
Nous pouvons vérifier que cette nouvelle image est effectivement disponible grâce
à la commande doc ker images , avec comme paramètre le nom de notre image (lemp-
symfony):
Les données de MariaDB seront stockées dans un volume Docker non exposé à
l'hôte. Nous aurions aussi pu choisir de définir un volume nommé afin de ne pas perdre
les données en cas d'arrêt ou de destruction du conteneur. Nous nous contenterons de
cette approche simplifiée pour les besoins de cet exercice.
9. 1 Un seul conteneur, plusieurs processus
Nous avons:
• un processus supervisord avec le PID 1, ce qui signifie qu'il officie comme
processus racine (celui qui est géré par Docker) ;
• nous avons ensuite un processus N ginx avec deux processus fils (les deux workers
de notre configuration) ;
• un processus PHP, FPM avec deux workers (valeur du paramètre pm.start_servers
de [Link]) ;
• un processus mysqld_safe (MariaDB) qui n 'a qu'un unique worker.
Superviser peut exposer un socket TCP sur laquelle un serveur HTTP écoute et permet
de contrôler le processus supervisord depuis une interface graphique.
Pour l'activer, il faut rajouter une section au fichier de configuration [Link] :
[ i net_ht tp_server]
port=9001
et ensuite exposer ce port via une commande EX POSE 9001 dans notre Dockerfile.
Le serveur supervisord est ensuite disponible via [Link] (pour peu
"'Cl
que vous ayez ajouté -p 9001 :9001 à la commande docker run au lancement du
0
c conteneur).
:::i
0
\.0
.-t Superviser Status - Mozilla Firefox D lC
0
N .J • Supervisor Status x \...+
@
.......
~localhost:9001_ _ _ _ _ _ _ _ _ _ __ ~ ~ Rech_er_ch_er_ _
..c
O'l
'i:
>-
Supervisor statuS
0.
0
u 1UFRESH 11 ~ESTART All 11 STOi' All 1
$docker exec - i -- user=apac he lemp /bi n/bas h -c 1cd /var/www/; symfony new
my_app 2. 81
Downloading Symfony ...
0 . 00 BI 5 . 17 MB :)}:)}:))}:))))}:)}:)}:)}(}:)))))))}:))}:):(}:)):)}:))}()}
................... . ....... . ................... . ...... . ....... . ............ . ................ . ...... . ....
0%
15 . 40 KB/ 5 . 17 MB .}. .}.. '.}{}' . } } )}'.}{}'. } '. }})'.}})) } '. }'.} '.}}}'.}'.)'.)}'.{ }})}{}{) }
. .. ... . ..... . . . . . . . . . . . . . . . .. .. ........ . .. .. . . . . . . . . . . ... . ......... .. . .. . .. .. . . . . .. .. ... .... . . ... . .
0%
31 . 40 KB/5 . 17 MB .}))}})})'.)'.}/{}}}}'.}'.}'.}' . }{}'.}'. }'.)}}})}}}}}'.}{}{}}}}
. .. . . .. . .. . ... .. .... . .. . . ... . .. . . .. . ... ... . . . .. . .. . . . .. . .... . .. ... .. . . .. . .. . . .. . .. . . . .. . .. . . . . . . . ... . ..
0%
4 7 . 40 KB / 5 . 17 MB :}{}{}:}})}:}{{}}}}):}}}:}{}:}{)}{}}}:} :}}}:} :} } }:} :: 0%
63 . 40 KB I 5 . 17 MB :)}}:/:(::(/((}:}}:}:(}}}:}:}}:)((}:}}:(}:}}:)}()}:/:(}}:}}::::
. . . .. . .. ... . ..... . . . . . . . . . . . . . . .. . ... ....... . .. .. . . . . . . . . . . . . . . ......... . .. .. . .. .. ... . .. .. ... .... . . . . . . .
1%
79 . 40 KB/5 .1 7 MB :}:} :}:}:}}}:}:} :):):}:}:}:}}):}:}:}:}:):}:}:}:}}}}}}}:}:)}}} 1%
95 40 KB/ 5 17 MB . -:-:-:-:-:·:-:-:·:-:-:-:·:-:-:·:-:-:-:·:-:-:-:·:-:-:-:-:-:-:·:-:-:·:-:-:-:-:-:-:·:-:-:·:-:-:-:-:-:-:·:-:-:·:-:-:-:-:·:-:-:-:-:-:·:-:-:·:-:-:·:-:-:-:·:-:-:·:-:-:-:-:-:-:-:·:-:-:·:-:-:-:·:-:-:·:-:-:·:- 1%
Q ue fait~elle ?
Elle se connecte à notre conteneur et lance la commande symfony à l'intérieur
du conten eur. C ela a pour conséquence qu'il n'est pas nécessaire d'avoir l'installeur
Symfony ni même PHP sur notre machine hôte !
Elle va ensuite télécharger le code de Symfony et initialiser notre application dans
le répertoire /var/www/. C e répertoire étan t mon té sur notre hôte, n otre code source
est d irectement éditable.
localhost
lemp-symfony
-0
0
c::
:::i
0
\.0
.-t
0
N
@
....... s_cJocker exec - Volume
..c:: 1 user=apache
O'l -/symfony_
ï:::::
>- app/code
0..
0
u
Dans notre commande docker exec, nous prec1sons que nous voulons que la
commande soit lancée en tant qu'utilisateur apache (- -user=apache ). Si nous ne
le faisons pas, Docker utilisera l'utilisateur root pour créer les répertoires de notre
application. Nous aurons alors un problème de permission sur notre volume (notre
utilisateur vagrant ne pourra pas accéder aux fichiers et donc les modifier).
Vous pouvez maintenant voir votre application tourner depuis votre hôte sur l'URL
[Link]
+ IOC~ftOU
Welcome to
Symfony 2.8 . 2
.... Î vou1 oppucauon 1s reaay to start [Link] on 1t at:
Y" /var/w.M./my_app/
"'Cl
0
c
:::i
~
,.,
"O
0 [Link];
\.0
.-t ~
0
N
V
V
, ,.
'ii
@ ·c
....... B
..c
:::;
CO Figure 9 .5 - Notre application totalement fonctionnelle
O'l c
0
ï::::: c
>-
o. c
0 ·3ù Pour finaliser la mise en place de notre environnement, créons le schéma dans
u :::;
"O
0
notre base de données avec la commande suivante :
....
c.
~
~
:::; $ docker exec -i -- user=apache l emp php /var/www/my_app/app/console
rS doctrine :database:create
1
"O
0
c
1 Crea ted database 'symf ony ' f or connection named defaul t
8
(Ç)
J23ol-------------------- Chapitre 9. Application mufti-conteneurs
$ ec ho -e "\ nal ias symf ony='docker exec -i --u ser=apache l emp php
1 /var/www/my_a pp/ app/conso l e'" » -! .bashrc
comme si Symfony était installé en local sur votre machine (n'oubliez pas de
relancer votre terminal pour prendre en compte l'alias symfony) .
9.1.8 En conclusion
Nous avons donc notre environnement de développement prêt et fonctionnel sans
avoir installé un seul mote ur d'exécution sur notre machine. Si vous avez besoin de
mettre à jour PHP ou de changer de base de données, une simple modification du
Dockerfile et un build suffiront pour mettre à niveau votre environnement.
Cependant, cette approche a quelques inconvénients :
-0
0
c::
:::i
• nous ne pouvons pas profiter des images du Docker Hub (si ce n'est l'image de
0 base de notre OS) ;
\.0
.-t
0 • notre configuration n'est pas en ligne avec une architecture micro,services
N
comme nous l'avons expliqué au chapitre 1 : elle n'est pas facilement scalable,
@
....... elle crée des dépendances fortes entre les processus et elle n e nous permet donc
..c::
O'l
ï:::::
pas de changer faci lement les caractéristiques de déplo iement.
>-
0..
0
u Voyons comment résoudre ces inconvénients avec une approche orientée micro,
services.
localhost
NGIVIX d
MariaDB
80
li
"9f«Wy"l l l
Chaque conteneur aura donc son propre Dockerfile (à l'exception de MariaDB car
nous utiliserons l'image officielle disponible sur le Hub Docker).
Tous les fichiers que nous allons utiliser dans le cadre de ce paragraphe sont
disponibles dans le répertoire micro-service . Par convention, nous avons utilisé un
sous-répertoire par conteneur qui contient le Dockerfile et les fichiers nécessaires à
la fabrication de l'image correspondante.
9.2.1 Nginx
Nous utiliserons maintenant l'image de base de Nginx que nous étendons en intégrant
"'Cl
0
nos spécificités :
c::
:::i
~
,.,
"O
0 [Link];
\.0 FROM ng i nx
.-t ~
0 V
N V
'&
·c
CO PY ngi nx .conf /etc/ ngi nx/ [Link]
@
....... B
:::;
COPY symfony .conf /etc/ ng i nx /sites·available/
..c::
O'l
CO
c
RUN mkd i r -p /etc/nginx/s i tes-enabled/ && \
ï::::: 0
c mkd ir -p /var/www/ && \
>- c
o.. l n - s /etc/nginx/s i tes -ava ilable/symfony .conf
u
0 ·3ù /e t c/nginx/s i tes -enab l ed/symfony
:::;
"O
0
....
c.
~ Comme vous pouvez le constater, notre Dockerfile est beaucoup plus simple que
~
:::; dans notre version initiale :
rS
"O
1
• il contient uniquement les informations nécessaires à Nginx ;
0
c
8 • nous n'avons plus besoin de nous occuper d'installation, d 'exposition du port,
(Ç) etc. Tout est déjà inclus et optimisé dans l'image de base.
12321-------------------- Chapitre 9. Application mufti-conteneurs
Dès que vous le pouvez, utilisez les images du Hub Docker ([Link]
en particulier les images officielles. Elles vous permettent de bénéficier des meilleures
pratiques et d'accélérer la mise en œuvre de solutions courantes.
9.2.2 PHP-FPM
Notre Dockerfile pour le conteneur PHP-FPM est relativement simple car il reprend
les mêmes commandes que dan s notre exemple précédent. La différence principale
réside dans la ligne CMD qui lance PHP-FPM et non plus Supervisor.
FROM centos :7
RUN curl - LsS https : //symfony . com/i nstal l er -o /usr/loca l /bin /symfony && \
chmod a+x /usr/ l ocal/ bi n/symfony
EXPOSE 9000
1 VO LUME /var/www
9.2 Application mufti-conteneurs ------------------------12331
Ce conteneur sera basé sur l'image busybox 1• C'est une image de taille minimale,
mais qui est largement suffisante pour ce conteneur.
Depuis la version 1.9 de Docker, il est possible d'utiliser des volumes nommés,
c'est-à-dire de créer des volumes (avec la commande docker volume) puis de les
associer à divers conteneurs. Cette alternative sera probablement à privilégier à
l'avenir, mais de nombreuses architectures utilisent encore le principe des data
containers. Il est donc utile de connaître ce pattern Docker.
Nos images étant prêtes, nous pouvons maintenant les utiliser pour nos conteneurs.
Démarrons déjà n otre data container qui va contenir le code source de notre application
(et être par la suite lié aux conteneurs Nginx et PHP,fPM) :
1 $ docker create -v $HOM E/symfony -ap p/code/ : /var/www/ -- name code symfony-code
"'Cl
0 Nous ne faisons que créer ce conteneur, sans le démarrer, avec la commande
c
:::i
~
,., docker cr eate. Nous montons ensuite le répertoire où se trouve le code source de
"O
0 [Link];
\.0 notre application.
.-t ~
0 V
N V Démarrons ensuite Nginx et PHP,fPM en les liant à notre data container car ils
'ii
@ ·c vont tous les deux avoir besoin d'y accéder.
....... [Link];
..c CO
O'l c
0
ï::::: c
>- c N'oubliez pas d'arrêter le conteneur lemp créé lors de l'exercice précédent avec
o.
u
0 ·3ù doc ke r st op 1emp, sinon vous obtiendrez un message d'erreur indiquant que le port
:::;
"O
0
....
8000 est déjà en cours d'utilisation.
c.
~
~
:::;
rS
1
"O
0
c
8
(Ç) 1. [Link]
12341-------------------- Chapitre 9. Application mufti-conteneurs
$ docker r un -d -p 8000 :80 - -volumes -from code -- name nginx symf ony -nginx
ea 53c8 l fd485357732 b05c0400346769282240d9940ec93f 53c92af46648a l 58
$ docker r un -d --volumes -f r om code --name php symfony-php
1 Obc7a35166afb91a01d5c0433dl83e2bf5 1ebla3a6f8b460a8cce0e4978c9f18
Il ne nous reste plus qu'à démarrer notre conteneur MariaDB. Cette fois,ci,
nous utilisons le conteneur officiel MariaDB. Ce dernier nécessite une variable
d'en v ironnement contenant le mot de passe de l'utilisateur root pour démarrer.
..
9.3 LE RESEAU DOCKER
La communication entre conteneurs est un élément clé du succès de l'architecture
micro,serv ices et par conséquent de Docker. Elle repose sur la librairie libnetwork 1
qui est n ée de la volonté d'extraire le système de gestion du réseau du moteur. Elle
-0
0 implémente le modèle CNM (Container N etwork Madel) que nous allons brièvement
c
:::i présenter pour bien comprendre ensuite les différents types de réseaux que fournit
0
\.0
Docker.
.-t
0
N N ous lèverons finalement le secret sur la gestion d'iptables par Docker et la gestion
@ du ONS.
.......
..c
Ol
ï:::::
>-
0. 9.3.1 Libnetwork et le modèle CNM
0
u
Le modèle CNM est véritablement une abstraction pour la communication inter,
conteneurs (potentiellement déployés sur des h ôtes différents).
Elle repose sur trois composants principaux qui permettent de couvrir toutes les
topologies de réseaux.
1. h ttps://[Link]/docker/1ibn etwork
9.3 Le réseau Docker ----------------------------12351
Hôte 1 Hôte 2
Container
Sandbox
N ous avons:
• le sandbox : il contient la configuration réseau du conteneur. Elle inclut les
interfaces réseau (ethO... ), les tables de routage et les configurations ONS. Dans
le cas de Docker, il y en a une par conteneur et son implémentation est un
namespace 1 network de notre machine hôte ;
• le endpoint : il permet de relier un sandbox à un network. Dans n otre cas, ce
sera typiquement une paire veth. Un endpoint n'est lié qu'à un sandbox et un
network. U n conteneur aura donc autant de endpoints que de network auquel il
est connecté ;
• le network: c'est un ensemble de endpoints qui peuvent communiquer ensemble.
Il n 'est au final qu'une abstraction sur une implémentation d'un pilote (driver)
qui fournit les fonctionnalités de connectivité.
Libnetwork fournit plusieurs drivers que nous retrouvons plus lo in dans ce chapitre
car certains sont utilisés par Docker :
• null : c'est un driver un peu particulier qui signifie « pas de réseau » . Il est là par
souci de rétrocompatibilité au niveau de Docker ;
• overlay : ce driver est pour l'instant le seul qui permette une communicat ion
"O
0 entre plusieurs hôtes. Nous l'utiliserons dans le chapitre suivant qui est consacré
c ~
,.,
:::i
"O
à Docker Swarm ;
0 [Link];
\.0 • host: permet de rendre disponible la configuration de la machine hôte à notre
.-t
0
.,.,
~
conteneur ; le conteneur pe ut donc directement accéder à toutes les ressources
N
'1;:
@ ·c de l'hôte ;
....... [Link];
.c
O'l
CO
c • remote : ce n'est pas à proprement parler un driver, mais un proxy pour un driver
distant. Il permet d'intégrer des drivers externes tels que Weave2 ou Openstack
ï::::: 0
>- c
o. c
0 ·3ù Kuryr3 ;
u :::;
"O
0
....
c.
~
~
:::;
rS
1
"O
0 l. Pour plus d' information sur la notion de namespace, vous pouvez vous reporter au ch apitre l.
c
8 2. [Link] works/products/weave-net/
(Ç) 3. [Link] ub .com/openstack/k uryr
Chapitre 9. Application mufti-conteneurs
• bridge : ce driver se base sur un bridge Linux 1• Il n'est disponible qu'à l'intérieur
d'un même hôte.
Le driver bridge, qui est le driver historique de Docker, est encore celui qui est
utilisé par défaut. Nous allons voir en détail comment il fonctionne, maintenant que
nous avons une représentation claire du CNM.
Par volonté de simplicité, nous utiliserons de manière égale les termes réseau et
driver.
Notez que, tout comme pour les volumes, Docker propose à des tiers de fabriquer
des plugins pour des systèmes externes de gestion de réseau. Nous verrons donc
prochainement des spécialistes des équipements de routage et de sécurité proposer
des plugins pour gérer les réseaux de conteneurs.
Pour lister les réseaux disponibles pour nos conteneurs au niveau de notre démon
Docker sur notre hôte, nous utilisons la commande suivante :
$ docker networ k ls
NETWORK ID NAME DR IVER
b2d747bcd553 hast hast
8998ee49ca35 bridge bridge
758827c4904b none null
},
"Options ": (
"com .docker . network . bri dge .default_bridge ": "tr ue",
"com .docker . network . bri dge .enab l e_i cc ": "t r ue " ,
"com .docker . networ k. bri dge .enabl e_ip_masquerade ": "t r ue",
"com .docker . network . bri dge . host_binding_i pv4": "[Link]",
"com .docker . network . bri dge . name ": "doc kerO " ,
"com .docker . networ [Link] iv er .mt u": "1500"
}
Nous voyons que ce réseau est bien de type bridge et qu'il dispose des adresses
IP 172.17 .0.1/16. Lors de l'installation de Docker, ce dernier a créé un pont virtuel
Ethernet, n ommé dockerO sur notre machine h ôte. La commande i fconfi g nous
permet de voir les détails de cette interface :
$ i f confi g dockerO
"'Cl dockerO : f l ags=4099<UP , BROADCAST , MU LTI CAST> mtu 1500
0
c:: ~
,., i net 172. 17 .0.1 netmas k 255 . 255 .0.0 broadcas t 0.0. 0.0
:::i
0 "O i net6 fe80 : :42 :4ff :fe06 :bldd pre f ix len 64 scopei d Ox20<lin k>
[Link];
\.0 et her 02 :42 :04 :06 :bl :dd t xqueuel en 0 (Ethernet)
.-t ~
0 V RX pa ckets 2489 byt es 116961 (114 .2 Ki B)
N V
'& RX errors 0 drop ped 0 ove rr uns 0 f rame 0
@ ·c
....... B TX packets 2549 bytes 29591068 (28 . 2 MiB)
:::;
..c:: CO TX errors 0 dropped 0 over ru ns 0 ca r ri er 0 col l isions 0
O'l c
0
ï::::: c
>- c
o..
u
0 ·3ù Cette interface est elle~même connectée ensuite à l'interface réseau de l'h ôte et
:::;
"O
0
.... permet aux conteneurs de communiquer entre eux ainsi qu'avec l'extérieur.
c.
~
~
:::;
Au démarrage d'un conteneur, Docker crée une interface v irtue lle sur l'hôte avec
rS un nom du type veth4bdf012 et assigne une adresse IP libre. Cette interface est ensuite
1
"O
0
connectée à l'interface ethO de notre conteneur.
c
8
(Ç)
Chapitre 9. Application mufti-conteneurs
Dans le cas de notre application, nous aurons une configuration similaire à la figure
ci~dessous.
localhost
NGllllX Maria DB
Vous pouvez lister toutes les interfaces virtuelles connectées sur notre interface
dockerO avec la commande suivante :
Nos conteneurs sont don c tous sur le même réseau. Cela ne signifie pourtant pas
qu'ils se connaissent, qu'ils puissent être jo ints depuis l'extérieur du réseau ou qu'ils
puissent accéder à Internet.
"'Cl
0
c:: ~
,., 9.3.3 Communication entre conteneurs
:::i
"O
0 [Link];
\.0
.-t ~
La communication de nos conteneurs entre eux et avec le monde extérieur est
0 V
N V contrô lée à deux niveaux :
'&
@ ·c
....... B
:::;
• En premier lieu, au niveau de la machine h ôte : permet-elle le transfert des
..c:: CO
O'l c
0
paquets IP ?
ï::::: c
>- c • Ensuite par la configuration d'iptables qui gère le dialogue avec le monde
o..
u
0 ·3ù
:::; extérieur.
"O
0
....
c.
~
~
Transfert des paquets IP
:::;
rS Le fait que les paquets IP soient transmis (forwarded ) par la machine hôte est gouverné
1
"O
0
c
par la variable système (kernel) net.ipv4. conf. [Link]. Sa valeur courante est
8 simple à obtenir avec la commande suivante :
(Ç)
J24ol Chapitre 9. Application mufti-conteneurs
Docker et lptables
Iptables est un pare-feu logiciel présent par défaut dans la grande majorité des
distributions Linux. Il serait plus juste de parler d'iptables/[Link] car iptables n'est
finalement qu'un moyen de configuration de netfilter1 qui réalise effectivement le filtre
des paquets réseau au niveau du kernel Linux.
Le réseau Docker bridge (ainsi que tous les autres types de réseaux Docker) se base
sur iptables pour autoriser/refuser les connexions entre conteneurs.
Regardons maintenant comment Docker utilise iptables pour certains cas courants.
l. [Link] [Link]/
9.3 Le réseau Docker ----------------------------12411
Dans ce cas, notre réseau bridge ( 1 72.1 7 .0.0/16) pourra accéder à toute IP en dehors
de ce réseau. Il est bien sûr possible de bloquer l'accès des conteneurs à l'extérieur de
ce réseau en passant le paramètre - - i p - masq=f a1 se au démarrage du démon Docker.
Communications inter-conteneurs
Nous devons ici bien séparer deux types de réseau bridge Docker :
• nous avons le réseau prédéfini qui se nomme « bridge » et qui utilise le driver
libnetworl<. de type bridge. C'est le réseau historique de Docker;
• nous pouvons aussi créer un nouveau réseau privé de type bridge. Celui-ci résout
les limitations du réseau historique.
Nous précisons que nous voulons un type de réseau bridge avec l'option -d
(optionnelle car c'est la valeur par défaut). Docker crée automatiquement un pont
Ethernet et un sous-réseau.
NB : La commande doc ker network create accepte des paramètres qui permettent
de définir l'IP de la gateway ( - -gateway), le sous-réseau ( - -s ubnet au format CIDR)
et la plage d'IP ( - -i p-range ).
St arti ng Nmap 6.40 ( htt p: //nmap . org l at 2016 -01 -27 16:26 UTC
"'Cl
Nmap sca n report for mariadb (172 . 18 . 0.4)
0
c:: Host is up (0 . 000014s l atency) .
:::i Not shown: 999 cl osed ports
0
\.0
PORT STATE SERV ICE
.-t
0
3306/ t cp open mysq l
N MAC Address : 02 :42 :AC : l2 :00 :04 (Un known)
@
.......
..c:: Nmap done : 1 IP address (1 host up) scanned in 0. 35 s
O'l
ï::::: [r oot@1844d7 f 5d5e6 /]# nmap -T4 ng i nx
>-
0..
u
0 Starti ng Nmap 6.40 ( htt p: //nmap . org l at 2016-01-27 16:27 UTC
Nmap sca n report for nginx (172 .18. 0. 3)
Host is up (0 . 000014s l atency) .
Not shown : 999 cl osed ports
PORT STATE SERV ICE
80/tc p open http
MAC Address : 02 :42 :AC : l2 :00 :03 (Un known)
QUESTI ON SECTION :
;nginx . INA
; ; ANSWER SECTION :
ngi nx . 600INA172. 19 . 0.4
Query ti me : 0 msec
SERVER: 127 . 0.0.1 1#53(127. 0. 0. 11)
WHEN : Sun J un 26 09 : 09 : 09 UTC 2016
MSG SIZE rcvd : 44
Nous voyons que le serveur DNS a l'adresse [Link] , ce que nous confirme le
"'Cl
0 [Link] /etc/[Link]:
c::
:::i
~
,.,
"O
0 [Link];
\.0
.-t ~ r oot@bc a409b26400: /# cat /etc/re [Link]
0 V
N V search home
'&
·c nameserver 127 . 0.0.1 1
@
.......
..c::
O'l
B
:::;
CO
c
0
1 options ndots :O
ï::::: c
>- c
o.. U tilisons ce que nous venons d'apprendre pour faire fonctionner notre application
u
0 ·3ù
:::;
"O
Symfony.
0
....
c.
~
~
:::;
rS 9.3.4 Mise en œuvre sur notre application Symfony
1
"O
0
c
8 Ayant déjà créé notre réseau au chapitre précédent, il ne nous reste plus qu'à adapter
(Ç) nos fichiers de configuration pour qu'ils l'utilisent.
Chapitre 9. Application mufti-conteneurs
Nginx
Pour notre serveur N ginx, il faut que nous configurions la localisation de PHP,fPM :
au lieu de nous connecter à localhost, nous devons utiliser le conteneur php.
Éditons no tre fichier [Link] et remplaçons simplement l'IP [Link] par
ph p (le nom de notre conteneur) :
Il PROD
loca t i on~ A/app\ . php(/l$l
f as tcgi_pass php:9000 ;
PHP-FPM
"'Cl
Ici, nous n'avons que le fichier de connexion de base de données à modifier :
0
c::
:::i
0
\.0
$ vi $HOME/symf ony -app/code/my_ap p/a pp/con fi g/paramet ers .yml
.-t
0
N Il This f i le is auto-generated duri ng the composer instal l
@ parameters :
.......
..c:: data base_host : mari adb
O'l
·;:: database_port : 3306
>-
0.. data base_name : symf ony
0 database_user : root
u
database_password : root
ma il er_transport : smt p
Redémarrons n otre conteneur avec docke r restart ph p pour que notre configura,
tion soit prise en compte ; nous avons mainten ant une application utilisant tous les
bénéfi ces du réseau Docker :
9.4 Orchestration avec Docker Compose --------------------12451
• nous pouvons remplacer n'importe lequel de nos conteneurs, et il ne sera pas
nécessaire de reconfigurer les autres à partir du moment, où, bien sûr, son nom
ne change pas ;
• n ous n'avons plus à lier nos conteneurs manuellement lorsque n ous les démar~
rons.
N ous avons beaucoup progressé depuis notre première tentative avec un seul
conteneur. Nous pouvons cependant faire encore mieux. En effet , pour construire et
démarrer tous nos conteneurs, il faut un nombre important de commandes Docker et
nous devons n ous rappeler à chaque fois tous les paramètres à utiliser (port à exposer,
volumes, réseaux ... ).
H eureusement, Docker propose une solution pour documenter tout cela, Docker
C ompose.
"'Cl
0
c::
:::i
~
,., 9.4 .1 Introduction et premiers pas avec Docker Compose
"O
0 [Link];
\.0
.-t
0
~
V C ompose nécessite bien sûr que Docker soit installé sur votre hôte. Il peut être utilisé
N V
'&
·c
sous Mac OS X (inclus par défaut dans Docker ToolBox) et sous Linux, mais n'est pas
@
....... B
:::; encore pris en charge sous W indows.
..c:: CO
O'l c
ï::::: 0
c L'installation se fait en récupérant l'exécutable depuis le dépôt GitHub avec curl:
>- c
o..
u
0 ·3ù
:::;
"O
0
.... $ sudo su
c.
~ $ curl - L ht tps : //g it hub . com/docker/compose/releases/download/1. 7. 1/docker -
~
:::;
compose -' uname -s ' - ' uname -m' >
rS /usr/local/bi n/docker-compose
"O
1
$ chmod +x /u sr/ l ocal/bin/docker -compose
0
c $ /usr/loca l /b i n/docker -compose - -version
8 docker-compose version 1. 7. 1, build Oa9ab35
(Ç)
Chapitre 9. Application mufti-conteneurs
Il est tout à fait possible de fournir à Docker Compose un fichier avec un autre nom
à l'aide du paramètre - f . Il peut même accepter plusieurs fichiers de configuration :
dans ce cas, il fusionnera leur contenu.
Docker Compose utilise aussi la notion de projet. Il faut voir un projet comme une
instance de votre application. Par défaut, le nom du projet sera celui du répertoire
courant. On peut bien sûr en passer un autre avec le paramètre - p.
Mettons tout cela en œ uvre.
l. [Link]
9.4 Orchestration avec Docker Compose ---------------------12471
ports:
- 8000 :80
volumes_from:
- code
php :
build :
con t ext: php -fpm
conta iner_na me : php
vol umes_from :
- code
db :
image : mariadb :lO . l
conta iner_name : db
env i ro nment :
MYSOL_ROOT_PASSWORD : root
Nous retrouvons :
• le fait que nous utilisons la version 2 du format Compose ;
• un bloc servi ces : qui contient la définition de nos quatre conteneurs;
• pour ch aque conteneur, nous avons un paramètre bui l d qui permet de spécifier
le chemin du répertoire à utiliser comme contexte de création. Docker Compose
fabriquera une nouvelle version de notre image si nécessaire ;
• nous spécifions aussi le no m de nos conteneurs avec le paramètre
con t ai ner _na me . S i nous ne le spécifions pas, Docker Compose générera
automatiquement un nom à partir <lu nom <le projet et <lu nom <lu bloc (par
exemple, pour notre conteneur nginx, ce sera dockercompose_nginx_l) ;
• le paramètre depends_on permet de nous assurer que le conteneur php sera
disponible lors du démarrage de nginx. Si nous n 'avons pas ce paramètre, le
conteneur nginx s'arrête s'il démarre avant le conteneur php ;
• le reste des paramètres est relativement simple à comprendre et correspond dans
"'Cl leur syntaxe aux paramètres de la ligne de commande Docker.
0
c::
:::i
~
,.,
0 "O
[Link];
Démarrons notre service (il faut lancer la commande depuis le réperto ire qui
\.0
.-t ~ contient notre fichier docker~[Link]) :
0 V
N V
'&
@ ·c
.......
..c::
B
:::;
CO
1 $ /usr/local/ bi n/docker -compose up -d
O'l c
0
ï::::: c
>- c
o.. Cette commande va:
u
0 ·3ù
:::;
"O
0
.... • créer les images de nos services à partir de nos différents Dockerfile ;
c.
~
~
• pour ch aque image, démarrer un conten eur basé sur la configuration (ports,
:::;
rS volumes ... ) de notre fichier docker~[Link]. Le paramètre - d est iden tique
"O
1
à celui de Docker : nos conteneurs seront démarrés en mode démon ;
0
c
8 • créer un réseau (de type bridge) avec le nom de notre projet (ce que nous
(Ç) pouvons vérifier, après lancement, grâce à la commande docker network l s) .
Chapitre 9. Application mufti-conteneurs
Un des avantages majeurs de Docker Compose est qu'il est possible d'utiliser
la commande docker-compose up de manière répétée. Si la configuration de notre
application (c'est-à-dire notre fichier [Link]) ou une de nos images a
changé, Docker Compose va arrêter et redémarrer de nouveaux conteneurs. Et si nos
anciens conteneurs avaient des volumes, ces derniers seront attachés aux nouveaux,
garantissant que notre application soit toujours fonctionnelle sans perte de données.
Commande Résultat
docker-compose ps Liste les conteneurs de notre application.
docker-compose logs Affiche une vue agrégée de tous les logs de notre
application.
docker-compose start /docker-compose stop Démarre/arrête l'ensemble des conteneurs de
notre application.
docker-compose pause / docker-compose Met en pause/relance les processus qui tournent
un pause dans les conteneurs de notre application.
docker-compose rm Supprime tous les conteneurs de notre application.
Le paramètre -v permet de forcer la suppression
même si les conteneurs sont démarrés.
-0
0
c:: En résumé
:::i
0
\.0
Ce chapitre nous a permis de suivre pas à pas la création d'une application
.-t
0 multi-processus. Nous avons vu comment combiner plusieurs processus au sein d'un
N
@
même conteneur avec Supervisor. Même si la chose n'est pas recommandée, elle est
.......
..c::
toujours couramment pratiquée. Nous avons ensuite vu comment implémenter une
O'l
·;:: application à base de micro-services et, notamment, comment en configurer le réseau.
>-
0.. Enfin, nous nous sommes penchés sur Docker Compose, l'outil d'orchestration de la
0
u suite Docker pour centraliser et automatiser la création de nos services.
10
Intégration continue avec
Docker
1. [Link] io/
2. [Link]
10.1 Avant de commencer - - - - - - - - - - - - - - - - - - - - - - - - - - l2s 1 I
Localhost
GltHub
0
Dép6t
"./hello-world
Web Hook
j L =mJ
•
1 HeloWorld Job: Build
[JOb: Deploy Te&t )
Jo~ Deploy Prad J
•
(
Gitlab
G itLab est un conteneur qui intègre notamment l'outil de gestion de version Git.
N ous commencerons par forker le dépôt h ello;world présent dans le dépôt GitHub
de cet ouvrage. Ensuite, Gitlab sera utilisé comme source pour les builds Jenkins
et permettra de versionner l'application en définissant des tags correspondant aux
versions stables de l'application.
Le fork de l'application hello-world depuis GitHub est réalisé afin d'obtenir directement
"'Cl
0 une application fonctionnelle et correctement configurée. Cette opération n'est faite
c:: ~
,.,
0
:::i
"O qu'une seule fois et aucun push vers GitHub ne sera effectué.
[Link];
\.0
.-t ~
0 V
N V Le code de l'application sera touj ours « pushé » dans la branche master, ainsi cette
'&
@ ·c dernière contiendra en tout temps la dernière version de l'application . C omme cela
....... B
:::;
..c:: CO
est mentionné plus h aut, n ous utiliserons les tags pour marquer l'application à livrer
O'l c
0
ï::::: c en production.
>- c
o..
u
0 ·3ù
:::;
"O
0
.... Le Git flow
c.
~
~ L'utilisation de Git se fait généralement en respectant certaines conventions, notamment
:::;
rS au niveau des branches. Une convention communément utilisée est le Git flow.
1
"O
0
Le Git flow est représenté par deux branches principales, master et develop, ainsi que
c
8 par des branches secondaires pour la réalisation des fonctionnalités et la correction
(Ç) des anomalies (feature branches).
J2s2I------------------ Chapitre 10. Intégration continue avec Docker
La branche master représente la code base qui est actuellement en production, aucun
push n'y est directement effectué. La branche develop représente la code base incluant
les dernières fonctionnalités considérées comme développées. Lors d'une release, la
branche develop est ainsi fusionnée dans la branche master (afin que cette dernière
contienne la code base de production}.
Pour chaque nouvelle fonctionnalité ou anomalie, un développeur crée une branche
temporaire dans laquelle il « pushera » ses modifications. Une fois le développement
terminé, il demandera la fusion de sa branche dans la branche develop (et supprimera
généralement sa branche}. C'est ce qu'on nomme une pull request.
Par souci de simplification, nous ne respectons pas dans notre exemple le Git flow,
mais nous ne pouvons que vous encourager à le faire dans le cadre de vos projets.
Jenkins
Jenkins est utilisé pour construire (build en anglais) l'application sous la forme d'une
image Docker (en s'appuyant sur Gradle 1 , comme nous le verrons un peu plus lo in),
puis pour la déployer dans nos deux environnements, un de test et un autre de
production. Pour cela, nous aurons besoin de trois jobs :
• Build : ce job clonera la code base de l'application selon la version souhaitée
(c'est-à-dire soit la branche master, soit un tag représentant une version) et
con struira une image D ocke r contena nt n o tre application. Il d é léguera cette
tâche au conteneur Docker API ;
• Deploy test: ce job invoquera aussi l'API Docker distant (du conteneur Docker
API) afin d'instancier un conteneur basé sur l'image créée par le job Build.
Il utilisera touj ours l'image basée sur la branche master e t sera déclenché
automatiquement après tout build ;
• Deploy prod : ce job est assez similaire au précédent, à la différence qu'il faudra
"'Cl
0
c spécifier la version de l'image à utiliser (un tag dans notre cas).
:::i
0
\.0
.-t
Docker API
0
N
@
Docker API est un conteneur qui contiendra une API Docker distant (autrement dit
....... un « Docker dans Docker »). Il construira les images à la demande du job Jenkins
..c
O'l
ï:::::
Build, et démarrera des conteneurs à la demande des jobs Deploy test et Deploy prod.
>-
0.
0 Ces derniers seront ensuite embarqués directemen t dans le conteneur Docker APL
u
l. h ttp://[Link]/
10. 1 Avant de commencer -------------------------12531
Environnement de développement
L'environnement de développement est un conten eur, associé à un volume dev qui
contient une copie (ou p lutôt un clone ) du code, permettant de tester rapidement un
nouveau développement con çu localement. Le développemen t, à proprement parler,
sera quant à lui directement effectué depuis la mach in e h ôte.
Le code de l'application Hello W orld est fourni grâce à un fork dan s GitHub que
n ous ferons un peu p lus tard
Le fichier [Link]
Ce fichier contient, tout d'abord, les librairies à utiliser : SpringBoot (qui inclut
également le framework SpingMVC ) et GradleDockerPlugin qui perme t d'appeler
une API Docker distant :
bui ldscript {
repos i tories
mavenCentral ()
dependenc ies f
Ensuite, nous listons les actions à effectuer: compiler le code Java, mettre en place
le serveur d'application SpringBoot et utiliser l'API Docker distant :
A fin de simplifier la lecture, nous ajoutons des « import » utiles aux tâches Gradle
ci~dessous :
Nous créons un argument qui devra être donné lo rsque le script Gradle sera
invoqué. Cet argument décrit la version de l'application (par exemple, master ou
alors le numéro d'une version) :
"'Cl
0
c::
:::i
0
\.0
1 def appVersion = project . get Property( "appVersion" )
.-t
0
N
N ous indiquons le nom du jar souhaité pour la compilation Java. N ous omettons
@
....... volontairement la version , car celle~ci sera traitée au niveau de l'image Docker :
..c::
O'l
ï:::::
>-
0..
0 jar
u baseName "hellowor l d"
1
N ous spécifions la version de Java à utiliser :
sourceCompat i bi l i ty 1 .8
1 targetCompa t i bi l ity 1 .8
10. 1 Avant de commencer - - - - - - - - - - - - - - - - - - - - - - - - - - l2ssl
N ous ajoutons les librairies ut iles au démarrage du serveur d'application SpringBoot
(pour l'en v ironnement de développement):
repositories {
mavenCentral ()
dependencies {
compil e("[Link] ramework . boot : spr i ng-boot-starter -thyme l eaf ")
compile( "org .spri ng f ramework . boot : spr i ng- boot -devtoo ls "J
N ous donnons l'adresse de l'A PI Docker distant (nous verrons plus tard comment
démarrer le conteneur exposan t cette A PI) :
docker {
url = ' http : //doc ker -api :2375 '
1
Nous créons un e tâche qui va simplement copier le fichier Dockerfile au niveau
du répertoire contenant le résultat de la compilation Java. Il s'agit ici de simplifier les
chemins dans le Dockerfile :
"http: //downl oad .orac l e. com/otn -pu b/jav a/ j dk/8u77 -b03/ j re -8u77-li nux -x64 . rpm"
-0 / t mp/jdk-8-lin ux -x64. rpm
RUN yum -y ins t al l /tmp/jd k-8-l inux -[Link]
1 ENV JAVA_HOM E /usr/ j av a/l atest
Notons que l'application est conditionnée sous la forme d'un JAR unique qui inclut
le serveur d'application SpringBoot.
-
10.2 LA PREPARATION DES CONTENEURS
Dans cette section nous allons mettre en place les conteneurs nécessaires à notre
système d'intégration continue. Comme nous l'avons vu précédemment, nous aurons
besoin de quatre conteneurs :
1. GitLab;
2. Jenkins;
3. Docker A PI ;
4. environnement de développement.
10.2.1 Prérequis
Avant tout, nous avons besoin de configurer un réseau afin que nos conteneurs puissent
communiquer les uns avec les autres. Pour cela, nous créons un réseau de type bridge
"'Cl
0
dont le nom est my_ci:
c::
:::i
0
\.0
.-t
1 $ docker network crea te -d bri dge my_ci
0
N
@
....... 10.2.2 Le conteneur dépôt de code Gitlab
..c::
O'l
·;::
>-
0..
Nous utiliserons Git avec GitLab comme outil de gestion de code source. Ce dernier
0 étant très courant, une image Docker existe déjà sur le Docker Hub, et il nous suffit
u
de la démarrer :
$ docker r un -- detach
--net my_ci \
--hostname git l ab \
-p 8180 :80 -p 8122 :22 \
- -name gitl ab \
10.2 Lo préparation des conteneurs ---------------------12571
-- rest art al ways \
-- vol ume /home/vagrant/vo l umes/gi t la b/confi g: /et c/gi t la b \
--vol ume /home/vag rant/vo l umes/gi t l ab/ l ogs : /var/ l og/g i tlab
-- vol ume /home/vagrant/vol umes/gi t l ab/dat a : /var/opt/g i t l ab
gi t la b/git l ab- ce :8 .5.8-ce .O
Il est également possible de mapper le port 443 afin d'accéder à Gitlab via HTIPS;
nous avons volontairement omis ce mappage car nous ne l'utiliserons pas dans notre
exemple et nous souhaitons éviter les tracas liés à la gestion des certificats SSL.
La création de volumes permet de mettre à jour GitLab avec une nouvelle image
sans perdre les données.
A près le démarrage du conteneur, nous devons configurer l'URL de G itLab ainsi
que le timeout pour l'exécution des webhooks (car la valeur par défaut est trop faible
pour notre CI). Pour cela, nous ouvrons un terminal sur le conteneur ainsi lancé :
"'Cl
0
c:: ~
,., ## Latest optio ns l isted at htt ps : //g i tlab . com/gi t l ab-org/omnibus -
:::i
0 "O gi tl ab/ blob/master /fi les/g i t l ab -confi g-temp l at e/gi t l ab . rb . template
[Link];
\.0
.-t ~
0 V fffl Ur 1 on whi ch Git Lab wi 11 be r eac hab1e .
V
N
'& ##For more det ai l s on conf i guri ng ext ern al_url see :
@ ·c
B ## ht tps : //gi t lab .com/git l ab -org/omn i bus-
....... :::;
..c:: CO gi t l ab/blob/629def0a7a26e7c2326566f0758d4a27857b 52a3/README .md#configuring -t he -
O'l c
ï::::: 0
c exter na l -url -for -gi t l ab
>- c ff ext erna l_ur l 'G ENERATEO_EXT ERNAL_URL' ff default : htt p: / /hostname
o..
u
0 ·3ù externa l _url 'http: //gitlab: 8180'
:::;
"O
0
gitl ab_rail s['webhook_t i meout' ] = 30
....
c.
~
~ ##Note : conf ig ura t i on set ti ngs be l ow are optiona l.
:::;
rS ## Uncomment and change t he va l ue .
"O
1 #ff#ffffffff#ff#######/f#/l####/f####
0
c # git l ab. yml confi guration ff
8 ####ff#fffffl#ffflffffflffff#lllf#ll#flll##ll
(Ç)
J2ssl------------------ Chapitre 10. Intégration continue avec Docker
1 root@gitlab : /# ex i t
Notons que puisque le dossier /etc/gidab du conteneur est un volume monté sur un
répertoire de notre hôte, nous aurions aussi pu faire cette modification directement
depuis l'hôte. Néanmoins nous aurions dû prendre garde aux problèmes de droits
que nous avons déjà évoqués dans le chapitre 9. Le résultat est , quoi qu'il en soit,
identique.
Finalement, nous devons redémarrer le conteneur pour qu'il prenne en compte ces
modifications :
Nous utiliserons Jenkins comme outil d'intégration continue. Tout comme pour
G itLab, une image standard du Docker Hub, prête à l'emplo i, peut être utilisée.
Dé marrons un conteneur :
$ docker r un --detach
-- net my_c i \
-- hostname j enk i ns \
-u root \
-p 8080 :8080 -p 50000 : 50000 \
-- name jenk ins \
--volume /home/vagrant/volumes/ j enk in s : /var/jenki ns_home \
jenk i nsci/jenk i ns:2 . 0-beta -l
-0
0
c::
::i Comme nous pouvons le voir dans la dernière ligne ci-dessus, nous utilisons
0
\.0
une version beta de Jenkins. N ous avons fait ce cho ix afin de présen ter la dernière
.-t
0 mon ture de Jenkins qui sera tout prochainement disponible. Il est évident que pour
N
@ une vraie application ce ch o ix ne serait pas judicieux, néanmo ins cela ne porte pas à
.......
..c:: conséquence pour notre exemple .
O'l
ï:::::
>-
0..
u
0 10.2.4 Le conteneur d'API Docker distant Docker API
L'API Docker représente un Docker dans Docker. Ici aussi, une image est déjà
existante ; démarrons-la :
- -pr i vi l eged est nécessaire pour qu'un Docker dans Docker fonctionne correc-
tement, cependant il est important de comprendre que cette option donne un accès
complet à l'hôte, si bien qu'elle doit être utilisée avec une grande précaution .
FROM centos :7
$ doc ker crea t e -v /home/vagrant /vol umes / devenv/he l lo -wor l d/ : /var/hel l o-world/
1 -- name=devenv-vol ume devenv -vo l ume
} .
"Options " : {}
Docker a automat iquement configuré tous les conteneurs afin qu'ils se connaissent
les uns les autres. Toutefois, ce n'est pas le cas de notre mach ine h ôte. Celui~ci peut
accéder aux conteneurs par l'intermédiaire de leur adresse IP, mais nous préféron s
permettre un appel via un nom de domaine.
N ous allons donc modifier la configuration de n otre hôte à cet effet :
1 $ sudo vi /etc/hasts
"'Cl
0 Nous ajoutons les lignes suivantes (en fin de fichier) :
c::
:::i
~
,.,
"O
0 [Link];
\.0
.-t
0
~
V
17 2. 18. 0. 3 jenk i ns
N V
'& 172 . 18 . 0. 4 docker -api
@
.......
·c
B
:::;
1 17 2. 18 . 0.2 gi t l ab
..c:: CO
O'l c
0
ï::::: c
>- c
o.. Attention, il convient de vérifier les IP en fonction des conteneurs (celles-ci étant
u
0 ·3ù
:::;
"O
allouées dynamiquement par Docker) selon le résultat de la commande docker
0
....
c. networ k ins pect my_ci .
~
~
:::;
rS Nous pouvons maintenant tester que l'A PI Docker fonctionne correctement:
1
"O
0
c
8
(Ç)
1 $ cur l http : //docker -api : 2375/images/json
J262I------------------ Chapitre 10. Intégration continue avec Docker
La première étape est de récupérer le code de l'application depuis GitHub. Pour cela,
nous commençons par initialiser GitLab.
Depuis un navigateur, allez à l'adresse suivante :
i
O'l
'i:
>- sudo chown vagra nt: vagran t /home/vagrant/volumes/devenv
0.
0 cd / home/vagrant/volumes /dev env
u 1 gi t clone htt p: //g it l ab :8180/root/hel lo -wor l d.g it
$ docker run -- rm -p 8090 :8090 --v ol umes -f rom=devenv -vo l ume --name=devenv
1 devenv
10.3 Configuration de notre Cl ----------------------------12631
NewProject
Want to hou se several depende nt p<OJKts u nder th@ sa me na~ce? Create a group
Import project from (") GitHub fi Bitbucket • [Link] [Link]'g G Google Code A l=ogbugz git Any repo by URL
Description (optional)
0 '(J Internai
The projed can becloned by any logged in user.
S ~ PubUc
The proJect can becloned without any authentication.
1§1§@• Cancel
L'avantage d'une telle approche est évident: il n 'est pas nécessaire d'avoir à
installer sur notre poste de travail G racile ou Java, ces derniers étant fournis par n otre
"'Cl
0
conteneur de développement.
c
:::i
~
,.,
"O
0 [Link];
\.0
.-t ~
10.3.3 Configuration de Jenkins
0 V
N V
'ii
@ ·c N ous allons mainten ant configurer Jenkins, notamment les plugins à utiliser et la
....... B
..c
:::;
CO gestion des permissions.
O'l c
0
ï::::: c
>-
o. c
0 ·3ù Installation des plugins et création de /'utilisateur admin
u :::;
"O
0
.... Depuis un navigateur, allons à l'adresse suivan te :
c.
~
~
:::;
rS 1 htt p: //jenki ns :8080/
1
"O
0
c L'écran suivant est affi ché :
8
(Ç)
Chapitre 1O. Intégration continue avec Docker
Getting Started
Unlock Jenkins
To ensure Jenkins is securely set up by the administrator, a password has been
generated and written to the file on the Jenkins server here:
Ivar /jenk ins_home/sec rets/1n1 t ialAdminPasswo rd
$ sudo ca t /home/vag rant /vo l umes/jen ki ns/secrets/ ini tialAdmi nPa ssword
1 e5f 5c2489a454e229f7 l f019494 fbc49
Dans notre cas, le mot de passe est « e5f5c2489a4 54e229f7lf019494fbc49 » , et il
suffit de le saisir dans l'écran, puis de cliquer sur Continue.
Le système nous demande ensuite le type d'installation que nous souhaitons.
Nous choisissons lnstall suggested plugins, en cliquant simplement sur le bouton
correspondant :
1 J
Installation de Gradle
A fin de pouvo ir construire notre application , nous devons configurer Gradle :
1. C liquez sur Administrer Jenkins (dans le menu à gauche).
2. Cliq uez sur Global Tool Configuration.
3. Descendez dans la page au niveau du titre Gradle.
4. C liquez sur Add Gradle.
5. Sous Name, saisissez« Grad le 2.12 ».
Gradle
~ lnstall automatlcally
Créer un utilisateur
Nom d'utilisateur: gitlab
Mot de passe:
Creer un ut1hs"'teu1
0 Mode legacy
Utilisateur/groupe
AdministerConfigureUpdateCenterReadRunScriptsUploadPluginsCreateDeleteManageOomainsUpdateViewBuildConfigureConnectCreateOel•
a admin li!' li!' l>I!/ l>I!/ li!' li!' li!' li!' li!' li!' li! li!' li!' l>I!/
a gitlab 0 D li! D 0 0 0 D 0 0 D D D 0 C
Anonyme 0 D D D 0 0 0 0 0 0 D 0 0 0 c
N ous allons mainten ant préparer les trois jobs décrits précédemment: celui pour
la construction de l'image et ceux traitant du déplo iement de l'application (sous la
forme de conteneurs) pour l'environnement de test et celui de production. Nous
créerons également le webhook dans GitLab qui déclenchera le build et le déploiement
automatiques sur l'environnement de test.
Le job Build
Nous créons dans Jenkins le job qui construira notre application:
1. C liquez dans le menu à gauche sur Nouveau Item (sic).
2. Sous New item name... , saisissez« hello~world » .
Plus bas, cochez Ce build a des paramètres, et créez deux paramètres de type
Paramètre String :
Nom: appVersion ; Valeur par défaut: master
N om: gitPath ; Valeur par défaut : *
Chapitre 1O. Intégration continue avec Docker
Nom appVersion
Description
Nom gitPath
Description
0 Aucune
8 Git
Repositories
"'Cl Repository URL [Link]
0
c
0
:::i Credentials . none . .:J .. Add
..
\.0
.-t Avancé ...
0
N Add Reposltory
@
.......
..c Branches to build
O'l Branch Specrtier (blank for 'any') $gitPath/$appVersion
'i:
>-
0. Add Branch
0
u
Navigateur de la base de code (Auto)
Q [Link]
0 Construire périodiquement
cl ean
bui ld lma ge
1 -PappVersion=$ appVersion
"'Cl
0 cl ea n permet de nettoyer le résultat d'une précédente exécution G radle,
c:: ~
,.,
:::i
"O
bui l dimage exécute la tâche du même nom présente dans le [Link] de [Link]~
0 [Link];
\.0 ration Gradle, et - PappVe r s i on=$ap pVers i on permet de spécifier la version de
.-t ~
0 V
V
l'image Docker qu i sera créée ; logiquement, cette dernière est alignée avec la
N
'& branche ou le tag (pour une release) utilisés dans GitLab.
@ ·c
....... B
:::;
..c:: CO
9. C liquez sur Sauver (en bas de page) .
O'l c
0
ï::::: c
>- c
o..
u
0 ·3ù Le webhook dans Gitlab
:::;
"O
0
.... Le webhook dans GitLab permet le déclen chement automatique d'un build Jenkins
c.
~
~
:::;
après tout push dans G it. Sa création se fait ainsi :
rS 1. O uvrez le projet he llo~world dans G itLab.
1
"O
0
c 2. C liquez sur Edit project ([Link] 10.13 ).
8
(Ç) 3. Dans le menu de gauche, cliquez sur Web Hooks.
Chapitre 1O. Intégration continue avec Docker
Build
Switches
Tasks clean
buildlmage
-PappVerslon=S appVerslon
Build File
Specify Gradle build 1ile to run. Also. some environment variables are available to the build
illiJ1!
to use workspace 0
BjiifiiE ~A_PP_'Y_AH~
Figure 10.12 - Définition du script de build <appel Gradle)
Edit Proiect
Leave Project
'8 Jenkins
Jenkins hello-world
État
Projet hello-world
:;;. Modifications
Répertoire de travail
Liens permanents
Historique des builds tendance =
• Dernier build (#10) il y a J mn JO s
• Dernier build stable (#10) il y a J mn JO s
'~d ~ • Dernier build avec succès (#10) il y a J mn JO s
• Last completed build (#10) il y a J mn JO s
tt1 3 avr. 2016 11:21
-0
0
c:: Le job de déploiement de /'environnement de test Deploy test
::i
0
\.0 N ous créons ensuite dans Jenkins le job qui démarrera un conteneur pour notre
.-t
0
N
environnement de test. Pour rappel, ce conteneur sera localisé dans le conteneur
@ docker,api, et sera créé grâce à l'API Docker distant présente dans ce dernier:
.......
..c:: 1. C liquez dans le menu à gauche sur Nouveau Item (sic) .
O'l
·;::
>-
0.. 2. Sous New item name .. . , saisissez« deploy,test,hello,world ».
0
u
3. Choisissez Construire un projet free,style.
4. Cliquez sur OK.
5. Pour l'onglet Ce qui déclenche le build :
C liquez sur Construire après le build sur d'autres projets (afin de déployer automa,
tiquement l'environnement de test après tout push dans G itlab).
Sous Projet à surveiller, saisissez « hello,world ».
Chapitre 1O. Intégration continue avec Docker
Ce genre de projet doit être protégé afin de limiter son accès aux personnes autorisées
car il pourrait contenir des données sensibles, telles que des mots de passe. Dans
notre cas, nous le laissons « Public » pour simplifier le processus.
Administrator /environnements v
E
environnements Q
'O' Star
0 Newlssue
. . Newtag
Command line instructions
Figure 10.16 - Création d'un repo Git pour contenir les propriétés d'environnement
Cette fois-ci notre CI est prête ! Nous allons dans la prochaine section illustrer
son exploitation par un exemple.
Un besoin métier a été exprimé: la couleur du « HelloWorld »ne doit plus être noire,
mais rouge. Un développeur est assigné et doit donc modifier le code de l'application,
"'Cl
0 le tester localement et « pusher » ses modifications.
c::
:::i
~
,.,
"O
0 [Link]; La modification demandée concerne la vue de l'application, soit le fichier suivant
\.0
.-t
0
~
V
(c'est-à-dire un fichier du volume devenv-volume):
N V
'&
@ ·c
B
....... :::; /home/vag rant /volumes/deve nv/he l l o-
..c::
O'l
ï:::::
>-
CO
c
0
c
c
1 worl d/src/mai n/resou rces/ t emplates/he ll o. ht ml
o..
u
0 ·3ù Ouvrons le fichier avec un éditeur de texte et modifions-le ainsi :
:::;
"O
0
....
c.
~
~ <!DOCTYPE HTM L>
:::;
rS <html xml ns :th= "http : //www . thyme l eaf .org ">
1 <head>
"O
0
c <t i tle>Getti ng Started : Serv i ng Web Cont en t </ ti tle>
8 <meta http -equiv= "Content -Type " content="text/ html: charset =UTF-8" !>
(Ç) <l head>
Chapitre 1O. Intégration continue avec Docker
<body>
<p st yl e="color: red ;" th : text= "' Hel l o, ' + $(name } + '' '" !>
<!body>
1 </ht ml >
N ous pouvons simplement tester n otre modification en démarrant notre conten eur
de développement :
1 $doc ker r un -- rm -p 8090 :8090 -- vo l umes -f rom devenv -vol ume -- name devenv
devenv
"'Cl
Si lors d'une commande git l'erreur suivante s'affich e :
0
c::
:::i
0 *** Pl ease tel l me who you are .
\.0
.-t Run
0
N gi t config -- gl obal user .emai l "yo u@exarnpl e. com "
@ gi t config -- gl obal user . name "Your Narne "
.......
..c::
O'l
·;::
>-
0..
il faut alors spécifier votre nom e t adresse email grâce aux commandes suivantes :
0
u
$ gi t config -- globa l user .ema i l "you@exarnple . com "
1 $ gi t config -- globa l us er . name "Your Name "
N ous vous rappelon s que n ous avon s installé un webhook dans G itLab afin de
builder et déployer en test automatiquement no tre application après tout push.
Vérifion s que tout s'est bien déroulé dan s Jenkins:
10.4 L'exploitation de notre Cl ---------------------------12111
.. J enkins (Ï) Adm1111st1 at e 111 1se deconn ecter
Jenk..ins
Ali +
Utilisateurs
1 Au repos
2 Au repos
Figure 10.17 - Résultat d'un build et d'un déploiement en test dans Jenkins
Les tests applicatifs (dans notre cas, la vérification de la couleur rouge) sont positifs.
Une mise en production de l'application est désormais souhaitée. Pour cela, nous
devons « releaser » le code, et nous utiliserons un tag git pour y parvenir.
"'Cl Lors d'une mise en production, dans un mode d'intégration continue, il convient
0
c:: ~
,., d'avertir tous les développeurs de ne plus« pusher »de code dans la branche courante
:::i
0 "O
[Link];
<master dans notre cas) afin d'éviter toute altération du code avant la release.
\.0
.-t ~
0 V
N V Ouvrons le projet hello-world dans GitLab et cliquons sur « 0 tags » d ans le
'&
@ ·c panneau principal :
....... B
:::;
..c:: CO
O'l c
0
Créons un nouveau tag :
ï::::: c
>- c
o.. 1. C liquez sur New tag.
u
0 ·3ù
:::;
"O
0
2. Pour Tag name, saisir « v 1.0.0 » .
....
c.
~ Par con vention, les noms de tags git suivent le format vX.Y.Z, où v signifie
~
:::; version, X le numéro de version majeure, Y le numéro de version mineure et Z
rS le numéro utilisé pour des corrections d 'anomalie.
1
"O
0
c 3. Sous Create from, saisissez « master ».
8
(Ç) 4. C liquez sur Create tag.
Chapitre 1O. Intégration continue avec Docker
hello-world Q
l i commits 1 branch ~ 0.29 MB Add Changelog Add License Add Contribution guide
Le tag est maintenant créé. Nous pouvons ainsi construire le conteneur qui lui
est associé (car par défaut notre job de build construit un conteneur pour la branch e
master). Pour cela nous ut ilisons Jen kins.
1. C liquez sur le projet hello,world.
2. C liquez sur Build with Parameters.
3. Pour appVersion, saisissez« vl.0.0 ».
Vous vous souvenez que le build hello-world déclenche, après un succès, le job
deploy-test-hello-world. Ce déclenchement est également valable lorsque le build est
"Cl exécuté à la main. Ainsi, dans notre cas, nous pourrons constater qu'un nouveau
0
c:: déploiement sur l'environnement de test sera effectué (basé sur la branche master).
:::i
0 Ce dernier n'aura toutefois aucune utilité, mais il n'est pas dérangeant.
\.0
.-t
0
N Dès la fin de la construction du conteneur, nous pouvons l'utiliser grâce au job de
@
.......
déplo iement de l'environnement de production. A insi, toujours dans Jenkins:
..c::
Ol
ï::::: 1. C liquez sur le projet deploy,prod,hello,world.
>-
0..
0 2. C liquez sur Build with Parameters.
u
3. Pour appVersion, saisissez« vl.0.0 ».
À ce stade, tous les environnements sont alignés, dans le sens où ils ont tous exacte-
ment la même version du code. A fin de constater qu'il s'agit bien d 'en vironnements
différents, notamment au niveau du test et de la production , nous allons utiliser le
pré texte d 'une anomalie qui doit être corrigée : dans no tre cas, il s'agira de la v irgule
en tre le mot « hello » et le nom fourni en paramètre.
La vue doit ainsi être corrigée. Pour cela, éditons le [Link] et supprimons la virgule :
<!DOCTYPE HTML>
<html xml ns :th=" http : //www . t hyme l eaf .org ">
<head>
<tit le>Getting Started: Serving Web Cont en t </ t i tle>
<meta ht tp-eq uiv="Content- Type " content="text/html: charset=UTF-8 " !>
<lhead>
<body>
<p style="color : red ; " th :text=" 1 Hello 1 + ${n ame ) + 1 1 1 • !>
<!body>
<l html>
$ docker run -- rm -p 8090 :8090 -- vo l umes -from devenv -vo lume -- name devenv
1 devenv
Si nous accédons avec un navigateur à nos trois en vironnements, nous obtiendrons
le résultat décrit dans le tableau ci-dessous (la couleur rouge n'est ici pas représentée) :
Environnement URL Résultat
Développement [Link] me=John Hello John!
Test [Link] Hello, John!
Production [Link] /hello?name=John Hello, John!
"'Cl
0 Logiquement, seul l'e nvironnement de développement est impacté.
c
:::i
~
,.,
"O
0 [Link]; Publio ns la modification :
\.0
.-t ~
0 V
N V
'ii $ cd /home /v ag ran t/ vo l umes/devenv/ hel l o-world/
@ ·c
....... [Link]; $ gi t add src/main/resources/temp l ates/hel l [Link]
..c CO
$ git commi t -m"Suppression virgul e"
O'l c
ï:::::
>-
o.
0
c
c
1 $ gi t push orig i n mas ter :ma ster
u
0 ·3ù
:::;
"O C omme précédemment, l'en vironnement de test est automatiquement construit
0
....
c.
~
et déployé .
~
:::;
En accédant (après le déploiement) aux trois env ironnements avec un navigateur,
rS
1 cette fois-ci, les en vironnements de développement et de test sont impactés, et
"O
0
c l'en vironnement de production reste inchan gé :
8
(Ç)
J2sol------------------ Chapitre 10. Intégration continue avec Docker
En résumé
Dans ce chapitre, n ous avons pu voir comment un système d'intégration continue
peut être facilement mis en place grâce à Docker. Nous avons pour cela utilisé deux
aspects:
- d'une part des images existantes (conçues par des tiers) contenant des outils
directement fonctionnels (dans notre exemple, il s'agissait de GitLab et Jenkins) ;
- d'autre part une architecture de déplo iement basée sur des conteneurs afin de
pouvoir tester très rapidement une application et la mettre en production le cas
échéant.
"'Cl
0
c
:::i
0
\.0
.-t
0
N
@
.......
..c
O'l
ï:::::
>-
0.
0
u
11
Docker Swarm
Service de
découverte Swarm Nede
(node 01)
! 1 Swarm Nede
(node p)
Swarm Master Swarm Master
(replica 1) (replica n)
"O
0
c
::i Figure 11.1 - Architecture générique d'un cluster Swarm
0
\.0
.-t
0
N
@
Docker Swarm permet même de gérer de manière transparente des hôtes localisés
.......
.c
dans des centres de calculs différents, voire chez des fournisseurs cloud différents.
O'l
ï::::: Une réflexion poussée sur les aspects opérationnels de gestion et de performance
>-
0. est, dans ce cas, obligatoire, et nous ne pouvons que vous conseiller l'article sur le
0
u site de Docker qui couvre ce sujet plus en détail 1•
1. h ttps://[Link]/swarm/plan-fo r-production/
11.1 D ocker Swarm ---------------------------12831
11 .1.1 Le service de découverte
Chacun dispose en général d'une interface de gestion REST qui permet aussi bien
l'enregistrement, le retrait des services et l'en voi de requêtes de découverte.
"'Cl
0
c
:::i
~
,., 11 .1.2 Maitre et nœuds Swarm
"O
0 [Link];
\.0
.-t ~
V
Q uand on parle de nœud du d uster, cela signifie simplement un hôte sur lequel tourne
0
N V
'ii le programme (binaire ) Swarm. C e programme dispose, comme nous l'avons vu dans
@ ·c
....... B
:::;
le chapitre 2, de deux modes de fonctionnement :
..c CO
O'l c
0
ï::::: c
>-
o. c
u
0 ·3ù
:::;
"O
0 1. Configuration and. Management Database
....
c. 2. [Link]
~
~ 3. h ttps://[Link]/docker/libkv
:::;
rS 4. [Link] io/
1
"O
0 5. [Link]
c
8 6. h ttps://[Link] [Link]/
(Ç) 7. [Link] [Link]/boltdb/bolt
Chapitre 11. Docker Swarm
• mode esclave. Les n œ uds Swarm sont simplement des hôtes sur lesquels nos
conteneurs vont tourner.
1. [Link]
2. [Link] html
11.2 Mise en œ uvre d'un cluster Swarm
localhost
swarm-node-01 swarm-node-02
1. [Link]
2. [Link] html
11.2 Mise en œuvre d 'un cluster Swarm
Nous pouvons d'ailleurs directement nous en servir pour voir que nous avons
maintenant un hôte Consul qui fournit le service Consul sur le port 8300 (qui est le
port RPC 1 utilisé pour la communication entre serveurs Consul) .
..
<::•
_,,_ ·-....... - ...,,.....
consul 0.2
.... ..,,. e
1 1
1 conlUI
·-1 .......
OICCKS
-
....
Serf Heallh Status
-
• --swarm- discove ry= "consul : // $(d ocker -mac hi ne ip cons ul ) :8500 " : spec1-
fie la localisation de notre service de découverte. Nous obtenons l'IP de notre
machine Consul avec la commande doc ke r- machine i p consu l et précisons le
port exposé HTIP ( 8500) ;
• --en gine-opt="cluster -s tore=cons ul : //$( docker-ma chi ne ip
consul ) : 8500" : ce paramètre permet de configurer le démon Docker qui sera
installé sur notre machine. Cela permettra à notre hôte de s'enregistrer comme
faisant partie de notre cluster ;
• -- eng i ne-opt="cl uster-a dve rt i se=et hl : 2376 ": adresse à laquelle notre
démon sera exposé et jo ignable sur notre cluster.
Si nous n ous connectons sur notre machine, nous pouvons vérifier que la configu-
ration s'est effectivement bien passée :
Nos deux conteneurs ne contiennent finalement que le binaire Swarm (et quelques
"'Cl
0
certificats CA nécessaire au mode TLS). C'est une technique efficace pour packager
c un exécutable et profiter ainsi du Docker Hub comme moyen de distribution. 11
:::i
0
\.0
est aussi possible d'installer manuellement le binaire de Docker Swarm, même si
.-t
0 l'intérêt est limité, comme le reconnaît d'ailleurs Docker lnc 2•
N
@
.......
..c Regardons plus en détail les processus docker/swarm qui tournent dans notre
O'l
ï::::: machine:
>-
0.
0
u
doc ker@swarm- mas te r : ~$ ps -ax
2636 ? Sl 0:12 /usr/ l ocal/bin /docker daemon -D -g /var/ l ib /docker
-H uni x: // -H tc p: //0 . 0. 0. 0: 2376 - -l abe l prov i der=vi rtualbox
1 -- cl uster -store=cons ul : // 192.168. 99 . 102:8500 -- cl us t er -advert i se=et hl: 2376
1. [Link]
2. [Link]
11.2 Mise en œuvre d'un cluster Swarm
'"'0 ..
~-oc-·--~I e
OOCKER/NOOES/ •
dOCkOf/nodes/192.1611.99.103:2370 [Link]ŒD
"'Cl
0
c::
:::i
~
,.,
"O
0 [Link];
\.0
.-t ~
0 V
N V
'&
@ ·c "49odl)l-11~------
....... B
:::;
..c:: CO
O'l c
0
ï::::: c
>- c
o..
u
0 ·3ù
:::;
"O
0
....
c.
~
~
:::;
Figure 11.4 - Nœuds Dockers enregistrés par Consul
rS
1
"O
0
c
8 Il est conseillé sur un environnement de production de ne pas avoir d'agent
(Ç) Swarm non~master sur l'hôte qui h éberge le Swarm Master, car cela évite d'avoir
Chapitre 11. Docker Swarm
des conteneurs qui se déploient sur ce serveur. Par défaut, Docker Machine en installe
un, ce qui peut être considéré comme un bug.
Sur le même principe, il ne nous reste plus qu'à créer nos deux nœuds esclaves.
L'unique différence est l'absence du paramètre -- swarm -mas t er, si bien que nous
n'aurons qu'un agent Swarm sur ces hôtes (ce sont donc des nœ uds esclaves) .
Connectons maintenant notre client Docker sur notre Swarm Master. Pour cela,
nous utilisons une légère variante de la commande que nous avons vue précédemment :
nous rajoutons le paramètre - - swa rm qui nous permet d'interagir avec le Swarm Master
(sur le port 3376). Si nous oublions ce paramètre, par défaut, notre client serait
configuré pour utiliser le port 2376 qui est notre démon Docker. Dans ce cas, nous
court~circuiterions Swarm et nous ne ferions que piloter un unique hôte.
Stopped : 0
Images : 3
Server Version : swarm/ 1. 1.3
Ro l e: primary
St rategy : spread
Fi lters : hea lt h, port . dependency , affinity , const rain t
Nades : 3
swarm -master : 192 .1 68 .99 . 107 : 2376
L Status : Healthy
L Cont ainers : 2
L Reserved CPUs : 0 / 1
L Reserved Memory : 0 B / 1. 021 GiB
L Labe l s : executiondr i ver=nat i ve -0.2. kerne l vers i on=4 . l . 19 -boot 2docker .
operat i ngsys t em=Boot2Doc ker 1. 10.3 (TC L 6.4. 1) ; master : 62511 7e - Thu Mar 10
22 :09 :02 UTC 2016, prov i der=v i rtualbox . storagedriver=aufs
L Error : (none)
L Upda t edAt: 2016 -03 -13T07 :38 :12Z
swarm-node-01 : 192 .168 .99 .108 :2376
L Stat us : Healthy
L Containers : 1
L Reserved CPUs : 0 / 1
L Reserved Memory : 0 B / 1.021 GiB
L Labe l s : executiondr i ver=nat i ve -0.2. kerne l vers i on=4 . l . 19-boot 2docker .
operat i ngsys t em=Boot2Doc ker 1. 10.3 (TC L 6.4 . 1) ; master : 62511 7e - Thu Mar 10
22 :09 :02 UTC 2016, prov i der=v i rtualbox . storagedr i ver=aufs
L Error : (none)
L UpdatedAt : 2016-03- 13T07:39 :04Z
swarm -node -02 : 192.168 .99. 109 :2376
L Stat us : Healthy
L Cont ainers : 1
L Reserved CPUs : 0 / 1
L Reserved Memory : 0 B / 1. 021 GiB
L Labe l s : execut i ondr i ver=nati ve-0 .2, ke r ne l vers i on=4 . l . 19-boot 2doc ker.
operatin gsystem=Boot2Doc ker 1. 10 .3 (TCL 6.4. 1) ; master : 625117e - Th u Mar 10
22 :09 :02 UTC 2016. prov i der=v i rtua l box . storagedr i ver=aufs
L Error : (none)
L UpdatedAt : 2016-03- 13T07:38 :38Z
Pl ugi ns :
"'Cl
Vo l ume :
0 Network :
c:: ~
,.,
:::i
"O
Kernel Version : 4.l. 19 -boot 2docker
0 [Link];
\.0
Operat i ng System : l i nux
.-t
0
~
V
Architect ure : amd64
N V
'&
CPUs : 3
@ ·c Tota l Memory : 3.064 GiB
....... B
..c::
:::;
CO Name : swarm -master
O'l c
0
ï::::: c
>-
o.. c
0 ·3ù Nous retrouvons bien n os trois nœuds avec le nombre de conteneurs actifs sur
u :::;
"O
0
chaque nœud: deux pour swarm,master (le Swarm Master et l'agent Swarm), un pour
....
~
c. chacun de n os nœ uds esclaves (uniquement l'agent Swarm).
~
:::;
Notre registre de service est totalement fonctionnel, et nos machines sont
rS
"O
1
maintenant prêtes. Nous pouvons donc déployer nos premiers conteneurs.
0
c
8
(Ç)
Chapitre 11. Docker Swarm
-
11.3 DEPLOYER UNE APPLICATION SUR UN CLUSTER
SWARM
11.3.1 Prise en main rapide
Abordons cela étape par étape pour bien comprendre comment Swarm orchestre
le déploiement de nos conteneurs. C ommençons, par exemple, par déployer quatre
conteneurs Nginx.
$ docke r r un -d -p 80 --name=nginx -2 ng i nx
$ docker r un -d -p 80 --name=nginx -3 ng i nx
Vous remarquerez que les commandes run prennent plus de temps qu'à la normale.
C'est que Docker doit, pour chaque nœud sur lequel le conteneur Nginx doit être
instancié, télécharger l'image depuis le Docker H ub. En effet, les images ne sont pas
partagées par les différents nœuds du cluster et doivent être disponibles dans le cache
local de chaque hôte. Ainsi la première fois qu'un conteneur est démarré sur un nœud,
l'image devra être téléchargée ; dans notre cas cela se produit pour les trois premiers
conteneurs car nous avons en tout trois nœuds disponibles (deux nœuds esclaves et le
nœud Swarm Master). Listons nos conteneurs :
Les filtres
Les filtres vous permettent de définir finement les règles de déploiement et de dire à
Swarm où instancier le conteneur.
Il existe cinq filtres répartis en deux types :
• les premiers se basent sur les attributs du nœud, plus particulièrement sur les
attributs du démon Docker directement. Ce sera soit des attributs standards
(la version du n oyau Linux, le système d'explo itation ... ), soit des étiquettes
personnalisées dé[Link] au niveau du démon. Regardons quelques exemples
utiles :
La liste des attributs utilisables dans les filtres s'obtient facilement avec la com-
mande docker i nf o et en regardant le champ Labels.
"'Cl
0 • les seconds types de filtres s'appliquent aux conteneurs eux-mêmes. Il est alors
c::
:::i
~
,.,
0 "O possible de regrouper des conteneurs ayant certaines affinités sur le même hôte
[Link];
\.0
.-t ~
ou partageant certaines dépendances. De nouveau, voici quelques exemples
0 V
N V intéressants à garder en tête :
'&
@ ·c
....... B
:::;
..c:: CO Commande à utiliser Commentaire
O'l c
ï::::: 0
c sur le Swarm Master
>- c
o.. $ docker run -d -e affinity:container=nginx-4 Déploie le conteneur nginx-10 sur le même
u
0 ·3ù
:::; -name=nginx-1 0 nginx nœud qu'un conteneur portant le nom « nginx-
"O
0
.... 4 ».
c.
~ $ docker run -d -e -e affinity:image= nginx - Déploie le conteneur nginx-11 sur un nœud
~
:::; name= nginx-1 1 nginx qui dispose déjà de l'image Nginx localement.
rS $ docker run -d -volumes-from=volume_ 1 - Déploie le conteneur nginx-12 sur le même
1
"O
0 name= nginx-12 nginx nœud que le conteneur volume_ 1 pour per-
c
mettre l'accès aux volumes de ce dernier.
8
(Ç)
Chapitre 11. Docker Swarm
Par défaut, Docker Swarm utilise la stratégie spread. S i nous reprenons nos
commandes dans l'ordre et regardons après chaque commande combien de conteneurs
nous avons sur chaque n œ ud, voici le résultat illustré dans un tableau :
Étape/commande Nombre de conteneurs par nœud
Initialement swarm-master : 2
swarm-node -01 : 1
swarm-node-02 : 1
$ docker run -d -p 80 -name=nginx-1 swarm-master : 2
nginx swarm-node -01 : 2 ( 1 + nginx-1>
swarm-node-02 : 1
$ docker run -d -p 80 -name=nginx-2 swarm-master : 2
l:l nginx
0 swarm-node -01 : 2
c
:::i swarm-node-02 : 2 (1 + nginx-2)
0
\.0 $ docker run -d -p 80 -name=nginx-3 swarm-master: 3 <2 + nginx-3> - N'oublions pas que
.-t
0 nginx nous avons un nœud esclave sur cet hôte !
N
swarm-node -01 : 2
@
....... swarm-node-02 : 2
..c
O'l
ï:::::
$ docker run -d -p 80 -name=nginx-4 swarm-master : 3
>- nginx swarm-node -01 : 3 (3 + nginx-4)
0.
0
u swarm-node-02 : 2
lntéressons,nous maintenant à un cas où nos conteneurs doivent communiquer les
uns avec les autres, tout en étant localisés sur des nœ uds différents.
1. [Link]
11.3 Déployer une application sur un cluster Swarm
N ous retrouvons pour chacun de nos nœuds, les trois réseaux standards de Docker :
bridge, null et host. Pour que nos conteneurs sur des hôtes différents puissent
communiquer entre eux, nous allons créer un nouveau réseau :
Notre réseau étant prêt, n ous allons pouvoir maintenant déployer quelques
conteneurs devant fonctionner de concert. Nous allons pour cela déployer un serveur
Gitlab.
$ eval $(doc ker -mac hin e env -- swarm swa rm -mas t er) #Nous uti l is ons not re Swarm
Mas ter
$ docker run --name git la b-postgresq l -d - -net=swarm -net - -env
'DB_NAME=g i t l abhq_producti on ' - -env 'DB_US ER=gi t l ab' --env 'DB_PASS=pass111ord'
- -env 'DB_EXTENS ION=pg_trgm' sameers bn/pos tgresq l : 9. 4- 17
$ doc ker r un -- name git la b -d -- net=swarm -net -p 10022 :22 -p 10080 :80 -- env
'GITLAB_PORT=l 0080' -- env 'GITLAB_SSH_PO RT=l 00 22' -- env
1 'GITLAB_SECRETS_DB_K EY_BASE=cdsp5439850' --env 'DB_HOST=gi t l ab-postgres ql ' - -env
1. h ttps://h [Link]/r/sameersbn/postgresq1/
11.3 Déployer une application sur un cluster Swarm
1
DB_PASS=password 1 -- env 1 DB_US ER=gi tl ab 1 -- env 1 REDIS_HOST=gitla b-red i s 1
1 sameersbn/g i tlab :8.6.l
De nouveau:
• nous avons attaché ce conteneur au réseau swarm~net ;
• nous avons défini les variables d'environnement n écessaires : DB_HOST et
REDIS_HOST sont particulièrement intéressantes car ce sont les noms d'hôtes
des deux conteneurs que nous avons créés précédemment. Ces variables sont
remplacées dans les différents fichiers de configuration de Gitlab pour les noms
d'hôtes de la base de données et du registre clé/valeur.
En listant nos conteneurs, nous voyons qu'ils ont été répartis par Docker Swarm
sur les différents nœuds de notre cluster :
Manage git repositories with fine grained access controls that keep Conf1rm new p115$word
N
'1;:
@ ·c
....... [Link]; Figure 11 .5 - Application Gitlab
.c CO
O'l c
0
ï::::: c
>-
o. c Nous pouvons aussi, bien sûr, ut iliser Docker Compose pour définir une application
u
0 ·3ù multi~conteneurs répartie sur plusieurs hôtes. Cette approche est même, avec quelques
:::;
"O
0
....
c.
limitations 1, totalement supportée par Docker Swarm.
~
~
:::;
rS
1
"O
0
c
8
(Ç) 1. h ttps://[Link]/compose/swarm/
Chapitre 11. Docker Swarm
Nous venons donc de déployer notre applicatif sur plusieurs hôtes et de manière
transparente.
En résumé
Dans ce chapitre, nous avons pu mettre en œuvre Swarm, le logiciel de clustering
l:l
0
c Docker à la base de l'offre CaaS de Docker. Nous avons vu comment instancier
:::i
0 une architecture à plusieurs nœuds s'appuyant sur un service de découverte comme
\.0
.-t
C onsul. N ous nous sommes enfin attachés à montrer le potentiel des filtres et des
0
N stratégies de déploiement pour influencer la distribution des conteneurs sur les
@ différents hôtes.
.......
..c
O'l
ï:::::
>-
0.
0
u
À travers les différents chapitres de ce livre, nous nous sommes attachés à donner une
vue aussi complète que possible de ce qu'est aujourd'hui Docker et la technologie des
conteneurs. En plus d'une présentation purement fonctionnelle, nous avons étudié
des exemples plus complexes et plus opérationnels.
Le lecteur aura sans doute compris la portée de cette petite révolution. Nous n'en
sommes qu'aux prémices de changements qui mettront probablement plus de dix ans
à se faire sentir dans le quotidien des départements informatiques des entreprises.
Commençons par un bilan des domaines d'application que nous avons abordés
précédemment.
"'Cl
0
c::
:::i
0
\.0
.-t
0
N
@
.......
..c::
O'l
·;::
>-
0..
0
u
LES DOMAINES D'APPLICATIONS EXISTANTS
Bien que ces usages ne soient encore que balbutiants (ou encore en maturation), nous
pouvons déjà entrevoir d'autres usages possibles pour Docker.
Domaine d'application Description
Bus d'intégration La plupart des ESB sont aujourd'hui construits sur la base d'une
logique de middleware relativement centralisée. Dans la pratique, il
s'agit de moteurs de workflow plus ou moins complexes associés à
des message queues <pour l'asynchronisme) et à des connecteurs.
Ce type d'architecture se prend parfois un peu les pieds dans le
tapis en imposant des modèles complexes de distribution de charge.
Par ailleurs certaines intégrations nécessitent des configurations OS
spécifiques qui sont souvent difficile à répliquer <et nécessitent parfois
de dédier une machine pour un connecteur).
Des initiatives comme Dray ([Link] proposent d'implémenter
des workflows sur la base de processus encapsulés dans des
conteneurs indépendants. L'avantage de ce type d'approche est
d'offrir une isolation forte de chaque étape du workflow <y compris
pour ce qui concerne les ressources système) tout en permettant
d'implémenter des configurations OS très spécifiques pour des
connecteurs exotiques.
Déploiement d'application Docker est déjà un moyen de distribution d'application sur le serveur.
sur le poste client Kitematic <que nous avons abordé dans le chapitre 3) offre une
interface graphique pour lancer des applications Docker sur son
poste client Windows ou Mac OSX.
Docker pourrait-il devenir un moyen alternatif aux package managers
et autres Windows installers pour déployer des applications sur le
poste client ?
Les deux prérequis sont de disposer d'une version native de Docker
pour ces deux OS desktop, ce qui est pratiquement le cas.
Le second prérequis sera de disposer d'images natives pour ces OS
capables d'exposer une interface graphique sur l'hôte.
Documentation Comme nous l'avons vu dans le chapitre 8, il est possible d'ajouter
automatique d'architecture de la méta-information aux images Docker par l'intermédiaire
"'Cl
de l'instruction LABEL. Par ailleurs, la commande docker i nspect
0 permet aussi de visualiser sous une forme JSON de nombreuses
c ~
,.,
:::i
"O
informations sur une image ou un conteneur.
0 [Link];
\.0 L'exploitation de cette méta-information est à la base des interfaces
.-t ~
0 V graphiques (pour le moment sommaires) des solutions CaaS.
N V
'ii Pour peu qu'un standard de méta-information pour les images
@ ·c
....... [Link];
Docker émerge et que le pattern « micro-services » soit implé-
..c CO
menté, on pourrait envisager des architectures auto-descriptives. La
O'l c
0
ï::::: c documentation (les dépendances, les services exposés) serait alors
>-
o. c contenue, non plus dans des documents, mais dans l'environnement
u
0 ·3ù d'exécution lui-même.
:::;
"O
0
....
c.
~
~
:::;
Autres applications potentielles pour Docker
rS
1
"O
0
c
8
(Ç)
-
LES DEFAUTS DE JEUNESSE DE DOCKER
Aussi intéressant que puisse être Docker, il faut reconnaître qu'il s'agit encore d'une
solution présentant des défauts de maturité. C eux,ci se corrigent peu à peu, mais
certains sont encore difficilement acceptables pour un exploitant prudent.
Sous C entOS, par exemple, un yum update de Docker provoque l'arrêt du Docker
engine et de tous ses conteneurs 1 • Dans certaines conditions, il arrive que les montages
de répertoires du host donnent, à l'intérieur du conteneur, une image incorrecte de
l'état des fichiers.
En dépit de ces défauts (bien référencés), l'usage de Docker en production s'accroît
chaque jour. Les éditeurs qui adoptent les conteneurs (et Docker en particulier) sont
nombreux et motivés. On ne peut donc douter que les avantages surpassent déjà les
incon vénients qui, par ailleurs, sont souvent surmontables pour peu que l'on s'appuie
sur une architecture adaptée.
Nous sommes con vaincus que Docker Inc. a semé en quelques années les germes
d'un changement profond. Cette petite startup française devenue l'une des valeurs
montantes de la Silicon Valley saura,elle en retirer les fruits ?
Difficile d 'en être certain. Le monde IT est très cruel avec les nouveaux entrants
dans le domaine des logiciels d'infrastructure, mais il ne fait aucun doute que des
géants comme Google, Microsoft ou Amazon ont déjà su tirer parti des avantages
technologiques des conteneurs.
Que Docker soit connu dans quelques années comme le nom d 'un projet open
source ou comme une société profitable du NASDAQ est difficile à prédire, mais il est
certain que nous utiliserons (peut,être sans le savoir) de plus en plus de conteneurs !
-0
0
c
:::i
0
\.0
.-t
0
N
@
.......
..c
O'l
'i:
>-
0.
0
u
1. h ttps://[Link]/docker/docker/issues/2658
Index
Les commandes apparaissent dans l'index en police à espacement fixe. Les commandes Docker
sont en minuscul es et les commandes Dockerfile sont en MAJUSCULES.
A CU 33, 123
cloud 45
AOD 167
cluste ring 23, 281
agent TI
déploiement d'application 292
AmazonAWSTI
CMD 158
Amazon ECS 45
CNM 234
Ansible 29, 48
commit 142
Apache Marathon 43
composition TI
Apach e Mesas 43
API Docker 258 Consul 285
API Docker Remote 68 Container as a Service Voir CaaS
application multi-conteneurs 217, 230 Container ID 100
ARG 192
conta iner layer î7
Atomic 8,22,85 [Link]
création de la VM89 accès 103
attach 138 arrêter 99
autorité de certification 203 clustering TI
Azure Container Service 46 commandes de gestion 136
communication 239
composition TI
"'Cl
0
B connexion. 103
c ~
,.,
:::i
"O Boot2Docker TI couche î7
0 [Link];
\.0 bridge 236 création. 98
.-t ~
0
N
V
V build 119, 141 création. d'une image 114
'ii
@ ·c cycle de vie 97, 132
B
....... :::;
dans une machine virtuelle 8
..c
O'l
ï:::::
CO
c
0
c
c définition 1î
>- c
o.
0 ·3ù CaaS 27, 12, 34 démarrage 98
u :::;
architecture 32 écosystème 20
"O
0
....
c. déploiement d'applications 29 fondations 9
~
~ solutions 35, 46 image TI,97
:::;
rS cache 155 infrastructure 25
1
"O
0
CentOST5,58 intermodal S
c
8 CGroups ÎÜ, 133 montage d'un répertoire 108
(Ç) Ch ef46 moteur d'exécution 20
multiple IT, 231 Docker Con tent Trust 206
orchestration TI Docker daemon 55, 68
OS spécialisé TI Docker Datacenter35
suppression 102 Docker Engine 9, 20, 143
conteneurisation 3 Docker H ub14
COPY 171
Docker in Docker 252, 258
copy on write 18
Docker Machine 56, 74, 287
CoreOS 8, TI, 45
commandes de gestion du démarrage 85
COW Voir copy on write
installation 74
cp 139
prise en main 75
create 102, 134
doc ker -mac hine create 76
docker -mac hine env 84
D docker-mach i ne inspect 8:3
daemo n 128 docker -mac hi ne l s 82
Data Center Operating System 24, 34, 43 Docker Remo te API 68, 203, 254
data container 233, 259 Docker Swarm 36, 282
data volume ï9 Docker ToolBox 55
DCOS Voir Data Center Operating System Docker Trusted Registry 36
démon 68, 128
Docker UCP 36, 38
déploiement 271
Dockerfile 115, 147, 183
stratégies 294
commentaires 150
devicemapper 19, 92
instruction format exécution 149
di ff 139
Docker instruction format terminal 148
alternatives TI instructions 150
avantages TI modèles d'instruction 147
clien t 66, 123 programmation 116
commandes système 128
configuration SSL 205
construction image originale 110 E
démon 128
"'Cl ENTRY PO IN T 160
0
c groupe 68
:::i
installation 55 ENV 183
0
\.0
.-t
installation automatisée 63 etcd 39, 45
0
N installation avec Docker Machine 77,Sî events 130
@ installation sur un hôte 73 exec 104, 137, 229
.......
..c intégration continue 249 export 140
O'l
'i: manipulation des images 141 EXPOSE 163
>-
0.
0 options des commandes 125
u réseau 234
réseau bridge 237 F
sécurisation 202
variables d'environnement 124 Fedora Atomic 8, 85
Docker A PI 252 Fleet 45
Docker Compose 35, 245 forward 239
commandes 248 FROM 150
Index
G libnetwork 234
ligne de commande Voir C U
GitLab 251, 256, 262
l oad 143
Google Con tainer Engine 45
load balancer 42
Gradle 253, 265
l ogi n 144
guest additions 60
l ogout 144
l ogs 136
H LXCD
hi story 119, 142
HyperV6
M
MAINTAINER 152
1
mappage des ports 165
IaaS 26, 27, 32 MariaDB 223
déploiement d'applications 28 micro-service 34, 42
limites29
image IT
de base 98 N
i mages Tiî, 117, 142
Namespaces TI, 235
i mport 143
i nfo 129 networ k 146
Infrastructure as a Service Voir IaaS Nginx 98, 220, 231, 244
i ns pect 106, 132 node 4î, 283
intégration continue 249 Notary 206
Iptables 240
0
J ON BUI LD198
OpenSSH 164
OpenVZD
"'Cl K orchestration 23, 245
0
c ~
,., overlay 295
:::i kemel7
"O
0 [Link];
\.0 ki 11 99, 132
.-t ~
0
N
V
V Kitematic 64 p
'ii
@ ·c kube-proxy 40
....... [Link]; pause 133
..c CO kubelet 40
O'l
ï:::::
c
0
Kubemetes 39 persistance19
>- c
o. c PHP-FPM 221, 232, 244
0 ·3ù architecture 39
u :::; modèle réseau 4T pod4T
"O
0
....
c. Kubemetes Contrai Plane 4T port 141
~
~
port IP 109
:::;
rS ps 100, 130
"O
1 L pu ll 144
0
c
LABE L 186 Puppet 29, 46, 52
8
(Ç) libcontainer 9 push 144
13061 Docker
R T
registry 14, 143 ta 9IB
privé 209 top 140
registry cloud16
rename 138
réseau'i34 u
restart 132
Rkt45 Ubemetes43
rm 102, 133 UCP Voir Universal Control Plane
rmi 112, 142 union file system Ï Ï
Rtk2T Universal Control Plane 36, 38
RUN 153 unpause 133
run 98, 104, 134 update 134
RunC2T USER 189
s V
save 143
scheduler4f, 44 Vagrant~
search 144 variables d'environnement 124
service de découverte 283 version 129
start 101, 132 VirtualBox 6, 9, 57, 81
stats 129 virtualisation matérielle 6, 27
stop 99, 132 VMWare6
STOPSIGNAL 201 volume 19, fil
storage driver19,93 création105"
Supervisor 224 VOLUMEl l i
Swarm282 volume 146
architecture 37
cluster 284
filtres 293
master 283
w
mode esclave184 wait 133
mode maître 284 Windows Nano Server22
node 283 Windows Serveur 201610
Symfony 220, 228, 243 WORKDIR 187