Cours - DOCKER
Cours - DOCKER
VINCENT LAINE
SOMMAIRE
◼ Conteneurisation Docker
◼ Run – port mapping
◼ Bénéfices des containers
◼ Run – volume mapping
◼ Apports pour les Dev-Ops
◼ Docker Commands
◼ Docker hub
◼ Inspect container
◼ NOTIONS DE BASE DOCKER
◼ Container logs
◼ OFFRES COMMERCIALES
◼ DOCKER FILE
◼ DOCKER COMPOSE
◼ Build Multistage
◼ DOCKER MACHINE
◼ TAG / PUSH / PULL
◼ DOCKER SWARM
◼ DOCKER ENGINE
◼ DOCKER HUB / REGISTRY
◼ FONCTIONNEMENT DES VOLUMES DE STOCKAGE EN CLUSTER
◼ Le réseau dans Docker (Que les 3 principaux)
◼ Variables d’environnement
CONTENEURISATION DOCKER
◼ Docker permet d'embarquer une application dans un ou plusieurs containers logiciels qui pourra s'exécuter sur
n'importe quel serveur machine.
Docker est une plate-forme de virtualisation par conteneur qui, à la différence de la virtualisation par hyperviseur
qui nécessite de créer une machine virtuelle embarquant un système d'exploitation invité pour s'assurer de son
indépendance avec la machine principale.
Il va permettre d'isoler une ou plusieurs applications dans des conteneurs en utilisant les ressources de la machine
hôte.
Docker doit pouvoir être exécutée sur n'importe quel environnement, quel que soit son contenu, évitant ainsi divers
problèmes de compatibilité entre les applications et l'hôte qui les exécute.
DOCKER
Avantages
◼ Un conteneur n'a besoin que de quelques centaines de Mo d'espace disque pour être déployé,
contrairement à une VM. Un conteneur va directement utiliser les ressources dont il a besoin sur le
serveur physique.
◼ La possibilité d'exploiter directement une application sans être contraint de modifier les librairies
installées sur la machine hôte ou de se soucier des versions des logiciels installés sur cette dernière.
◼ C'est un gain de temps non négligeable, l'administrateur système n'a plus autant à s'accorder avec
l'équipe de développement pour être certain que son serveur possédera toutes les dépendances
nécessaires au déploiement d'une application.
◼ La possibilité de partager la configuration complète d'une application sur n'importe quel poste grâce
aux Dockerfiles.
◼ Une simple exécution du fichier permet de déployer des conteneurs prêts à l'emploi, avec la possibilité
d'en modifier certains aspects sans affecter leur configuration.
DOCKER
Inconvénients
◼ Comme les conteneurs utilisent directement les ressources de la machine hôte, il est par exemple
impossible de déployer un conteneur basé sur un système d'exploitation Windows sur un serveur
physique Linux.
◼ Certaines applications ne se prêtent pas à un déploiement morcelé par couche car certaines d'entre
elles ne peuvent fonctionner que de façon monolithique, il est donc préférable d'effectuer des tests de
conteneurisation avant de se lancer dans un déploiement d'application déjà existante.
◼ Il peut être parfois difficile de définir une sécurité poussée entre les différents environnements Docker
d'une même machine physique, les conteneurs utilisant les ressources du noyau et des composants
systèmes de cette dernière, certaines situations ont plus de chance de se répercuter sur le système
d'exploitation sous-jacent ou sur d'autres conteneurs.
BÉNÉFICES DES CONTAINERS
◼ Agilité
◼ Les containers sont rapides et simples à mettre en œuvre
◼ Portabilité
◼ Les containers sont portables sur tout type d’environnement
◼ Du poste développeur, aux serveurs de l’entreprise, au plateformes cloud privées ou publiques
◼ Consistance
◼ Les containers ne subissent aucune modification du poste du développeur à l’environnement de production
◼ Ils sont conçus pour être réutilisés
◼ Optimisation des coûts
◼ Que ce soit en en termes de ressources nécessaires (RAM, stockage..) ou de management (agilité, portabilité…)
◼ Profite des coûts d’investissement plus bas du Cloud provider CAPEX/OPEX
◼ Elasticité
◼ Orchestrateur !
◼ Autoscaling
APPORTS POUR LES DEV-OPS
◼ Développeurs
◼ « build once… run everywhere »
◼ Le container est un environnement sécurisé, stable, portable sur tous environnements
◼ Il résout les problèmes de dépendances ou de packages manquant lors du déploiement
◼ Plusieurs versions de librairies peuvent être utilisées dans différentes containers du fait de leur isolation
◼ Forte automatisation de toutes les phases (test, intégration, packaging..)
◼ Réduit voire élimine les problèmes d’environnement clients différents de ceux de l’éditeur
◼ Rapidité de déploiement, de retour arrière comparativement aux VMs
◼ En définitif, tout semble simple et rapide !
APPORTS POUR LES DEVOPS
◼ Administrateurs
◼ « configure once… run everywhere »
◼ Rend le cycle de vie des applications plus efficace, consistant, et reproductible
◼ Améliore le rendu de la qualité du code développé
◼ Élimine définitivement les inconsistances entre les différents environnements de développement, test, et
production
◼ Apporte une répartition des responsabilités claire avec les développeurs
◼ Améliore sensiblement la vitesse et l’agilité des procédés d’intégration et de déploiement continu
◼ Améliore beaucoup d’aspects comparativement aux VMs du fait de leur taille réduite : performance, coûts,
déploiement, portabilité..
APPORTS POUR L’ENTREPRISE
◼ Stratégie cloud
◼ Facilite l’évolution vers le(s) cloud(s) public(s)
◼ Facilite l’évolution vers l’hybridation et le multi-clouds
◼ Stratégie DevOps
◼ Résout les problèmes de gestion des différents environnements par la consistance des containers
◼ Facilite les démarches d’intégration et de déploiement continu
◼ Facilite l’autoscaling des applications
LIMITES - MOBILITÉ DES CONTAINERS
◼ Registre
◼ Registre Docker public
◼ Registre privé
◼ Registre en mode SaaS
◼ Quay.io
◼ …
◼ Kubernetes
◼ 2017 meilleure gestion du stockage stateless/statefull sur les pods
LIMITES - INTEROPÉRABILITÉ ET VERROUILLAGE
◼ Docker
◼ A ce niveau, la portabilité est assurée par la nature même de Docker
◼ Simplement particularité containers Linux vs Windows
◼ containers Rocket / LXC…
◼ Isolation
◼ Isolation native entre les containers
◼ Partage de librairies pour l’optimisation mais en lecture seule
◼ Sécurité
◼ Kernel « hardened » > Grsecurity / PaX
◼ Linux Security Module
◼ SE Linux / AppArmor
◼ Os Minimaux / réduction de la surface d’attaque > CoreOS / Fedora Atomic / VMWare Photon…
DOCKER
Docker est une technologie de conteneurisation reposant sur le noyau Linux et ses fonctionnalités de
virtualisation par conteneurs (LXC pour Linux Containers), notamment :
◼ le composant cgroups pour contrôler et limiter l'utilisation des ressources pour un processus ou un groupe
de processus (utilisation de la RAM, CPU entre autres) associé au système d'initialisation systemd qui permet
de définir l'espace utilisateur et de gérer les processus associés ;
◼ les espaces de noms ou namespaces qui permettent de créer des environnements sécurisés de manière à
isoler les conteneurs et empêcher par exemple qu’un groupe puisse « voir » les ressources des autres
groupes.
Docker utilise des fonctionnalités natives au noyau Linux, comme les cgroups ou les namespaces, mais offre les
outils pour le faire de manière simplifiée pour permettre, entre autres :
◼ la duplication et la suppression des conteneurs ;
◼ l’accessibilité des conteneurs à travers la gestion des API et CLI ;
◼ la migration (à froid ou à chaud) de conteneurs.
DOCKER
Machine Virtuelle
◼ Basée sur un Hyperviseur
◼ Permet d’émuler des machines complètes : un Os avec une ou plusieurs applications
◼ Machine virtuelles lourdes (plusieurs giga)
Docker
◼ Plus léger, baser sur un moteur de conteneur (Docker)
◼ Sur la couche supérieure, on retrouve les applications installées dans chacun des conteneurs
◼ Un seul système d’exploitation, celui de la machine hôte qui fait bénéficier de ses ressources aux différents conteneurs
◼ Conteneur plus léger (rarement au-dessus de 500 Mo)
◼ Permet de segmenter une application en micro-service (un docker par service : apache, base de données …)
POURQUOI TANT D’ENGOUEMENT ? QUELLES SONT LES UTILISATIONS
POSSIBLES, EFFICACES ET PERTINENTES DE DOCKER ?
◼ Déployer rapidement un service lorsque l’on a besoin de le déployer plusieurs fois : cette
reproductibilité est la base de docker, c’est typiquement l’utilisation que peut en faire un fournisseur
de cloud.
◼ Distribuer une application : Docker en tant que "système de distribution d'une application" : n’ont plus
à packager une application sous différents systèmes (deb, rpm, etc)
◼ Développer et tester une application, Docker permet :
◼ de concevoir une architecture de test plus agile, chaque conteneur de test pouvant par exemple intégrer une
brique de l'application (base de données, langages, composants, …), le développeur pourra tester sur la même
machine plusieurs versions d'un même logiciel en inter changeant le conteneur correspondant.
◼ de développer une application selon le concept d’architecture de micro-services avec pour chaque couche des
conteneurs isolant les composants de l’application ;
◼ faciliter le process de mise à jour de l’application : les images Docker sont versionnées et permettent une mise à
jour simplifiée et maîtrisée. Le process de rollback est aussi simplifié : on redéploie la version précédente de
l’image.
◼ d’avoir un environnement de développement identique à l’environnement de production
DOCKER HUB
◼ C’est quoi ?
◼ https://hub.docker.com/
◼ Et celle de la communauté
◼ Développement
◼ Docker est développé en langage GO
◼ Le daemon Docker se base sur le pilote d’exécution RunC
◼ Control Group CGROUPS
◼ Allocation de ressources RAM et CPU aux containers
◼ Namespaces
◼ Isolation des containers
◼ système de fichiers, nom d’hôte, utilisateurs, réseau, processus
◼ UNION FILE SYSTEM UnionFS
◼ Stockage sur plusieurs couches en lecture seule
◼ Support d’autres pilotes de stockage en fonction des distributions (AUFS, devicemapper, BTRFS, Overlay)
◼ Format des containers Docker
◼ Namespaces + Cgroup + UnionFS
◼ Ce format par défaut est appelé LIBCONTAINER
NOTIONS DE BASE DOCKER
◼ Docker image
◼ Équivalent à une application complète composée de différentes couches liées.
◼ Docker container
◼ Correspond à l’exécution d’une image Docker + une couche de lecture/écriture
◼ Docker engine
◼ Crée, lance et exécute les containers Docker sur les plateformes physiques, virtuelles, en local, dans le
datacenter ou chez un fournisseur de cloud
◼ Docker hub / Registry service
◼ Service de stockage et de distribution des images dans le cloud ou sur un stockage d’entreprise
SYSTÈME EN COUCHES
◼ Fonctionnalités
◼ Gestion fine des droits d’accès
◼ Interface grahique (installation, administration, statistiques…)
◼ Signature des images
◼ Docker Trust Registry
◼ Version onpremise du Docker Hub privé
◼ QUAY.IO
◼ Registre en mode Cloud ou OnPremise
◼ Support d’images de type Docker et Rocket
◼ Fonctionnalités de géo-réplication
◼ CoreOS Enterprise Registry
◼ Registre OnPremise
◼ Support d’images Docker / Rocket
DOCKER COMPOSE
◼ Liens de containers
◼ Description YAML
DOCKER SWARM
◼ SWARM
◼ Clustering d’hôtes Docker
◼ Fonctionnalités d’orchestration
DOCKER SWARM
◼ Fonctionnalités
◼ Management de clusters Docker (déploiement, démarrage…)
◼ Mise à jour des nœuds
◼ Communication TLS
◼ Architecture déclarative de l’état désiré (composition de Dockers)
◼ Mode Spread (répartition intelligentes des Dockers sur les nœuds)
◼ Load-balancing
◼ Scaling (manuel!)
◼ Gestion du réseau inter-nœuds en overlay
◼ Stratégies
◼ Filtres / Labels (production, test, ..)
◼ État du nœud
◼ Affinité entre containers
◼ Dépendance entre containers (montages fichier..)
KITEMATIC
◼ Console GUI
◼ Visualisation de l’état de containers
◼ Manipulation des containers
◼ Accès en CLI aux containers
◼ Gestion de ports, logs, volumes de stockage..
SERVICES
◼ Docker Service Discovery
◼ Système d’enregistrement pour containers
◼ Équivalent mécanismes DHCP/DNS
◼ Réseau
◼ Docker – réseau Overlay (Swarm)
◼ Mécanismes de plugins :
◼ Openstack Neutron
◼ Weaveworks
◼ …
DIFFÉRENTES ÉDITIONS
◼ Community
◼ Docker / Compose / Swarm
◼ BASIC
◼ Community + infra, containers, plugins certifiés
◼ 750$ / hôte / an ou 75$ / mois
◼ STANDARD
◼ Basic + registre privé + Docker Datacenter + ldap + multi-tenancy
◼ Par hôte : 1500$/an ou 150$/mois
◼ AVANCEE
◼ Standard + sécurité des images
◼ Par hôte : 2000$/an ou 200$/mois
DOCKER ENGINE
◼ Moteur Docker
◼ Docker Daemon
◼ REST API pour piloter le daemon
◼ Command Line Interface
QUEL OS POUR L’HÔTE ?
◼ Distributions minimales
◼ Le choix idéal ! CoreOS, Fedora Atomic, RancherOS…
◼ • + Sécurisé + Cluster/Réseau + Léger
◼ - mature / stable ?
◼ Production ?
◼ Distribution
◼ Ubuntu / CentOS / Debian / Suse ….
◼ Adapté à la production : en Entreprise & Cloud providers
◼ + Support + Maitrisé + GUI
◼ - sécurisé ? - cluster ?
◼ Poste de développement
◼ Poste Linux : Ubuntu ou autre
◼ Poste Mac/Windows : VirtualBox / Distri minimale Boot2Docker
QUEL OS COMME BASE IMAGE?
◼ SCRATCH
◼ Pas d’OS
◼ Destiné à la création d’images minimales
◼ • + Modules (Kernel)
◼ Distributions minimales
◼ Ubuntu 188Mo
◼ CentOs 172Mo
◼ OS Minimaux
◼ Busybox 2Mo, Alpine 5Mo
◼ Lequel choisir ?
◼ L’OS le mieux maitrisé ?
◼ L’OS le plus léger ?
PLATEFORME DOCKER
◼ Composants de base
◼ Docker Engine
◼ Docker Registry / Hub
◼ Docker Hub
◼ Service de stockage d’images Docker en mode SaaS
◼ La version publique est gratuite et accessible par tous
◼ La version privée est payante et sécurisée
◼ Docker registry
◼ Version Opensource de Docker Hub
◼ Installation Onpremise
◼ API : push/pull/Search
◼ Pas de GUI, pas de gestion des droits d’accès
DOCKER
◼ Lorsqu’on lance un « docker run », docker cherche d’abord l’image en local, si elle n’est pas disponible, il la
télécharge depuis Docker Hub (par défaut). Une fois l’image présente en local, le conteneur est lancé.
Commande Description
Description:
◼ Pour améliorer la performance et la portabilité d’une infrastructure Swarm il est recommandé de ne
pas stocker les données importantes directement sur la couche d’écriture des conteneurs.
◼ Pour cela il faut utiliser les volumes.
◼ Les volumes sont des espaces de stockages qui peuvent être mappés sur
◼ plusieurs conteneurs/services en même temps.
◼ Docker Swarm met à disposition 3 types de volumes :
◼ Volume Data
◼ Volume Bind
◼ Volume tmpfs
VOLUME DATA
◼ Description :
◼ Le volume de type « data » est la solution de stockage de données la plus utilisée avec Docker Swarm.
◼ C’est le type de stockage par défaut de docker.
◼ Elle offre de nombreux avantages :
◼ Elle n’augmente pas la taille de la couche d’écriture du conteneur.
◼ Cycle de vie indépendant du conteneur/service.
◼ Peut être managé directement via la CLI Docker.
◼ Fonctionne aussi bien sous Linux que Windows.
◼ Facile à déplacer/sauvegarder.
◼ Permet l’utilisation de « volumes driver » pour stocker les données sur des espaces de stockages distants de l’hôte (NFS,
SAMBA, cloud, etc…).
◼ Les volumes docker de type data sont visibles dans le répertoire : /var/
VOLUME BIND
◼ Description :
◼ Le volume de type « bind » consiste à monter un chemin du filesystem de l’hôte directement dans le conteneur.
◼ Ce type de volume est historique à docker, mais il est préférable aujourd’hui d’utiliser les volumes de type « data
».
◼ Ce type de volume ne peut pas être managé via la CLI de Docker et est donc plus difficile à administrer.
◼ Si le chemin du volume « bind » n’existe pas à la création du conteneur, il sera automatiquement créé.
◼ Ce type de volume est dépendant de la structure de répertoire du filesystem.
VOLUME TMPFS
◼ Description :
◼ Ce type de volume permet de stocker de la donnée volatile directement sur la RAM de l’hôte.
◼ Ce type de volume dispose d’une performance très élevée.
◼ Contraintes :
◼ Uniquement disponible sur les hôtes docker Linux.
◼ Le cycle de vie du volume tmpfs est identique à celui du conteneur qui l’utilise.
◼ Un volume tmpfs ne peut être partagé entre plusieurs conteneurs/services.
RÉSUMÉ
RÉSUMÉ
LES VOLUMES DANS DOCKER
◼ Lorsque vous supprimer le conteneur, toutes vos modifications sont perdus car les fichiers sont stockés par
défaut dans ce conteneur
◼ Pour éviter ce problème, il est possible d’utiliser un volume qui sera situé sur la machine hôte
◼ Par défaut le réseau utilisé pour tous les conteneurs est le 172.17.0.0/16
◼ Docker assigne une ip automatiquement et dynamiquement dans ce range pour tout conteneur créé.
◼ Attention, si un conteneur redémarre, son ip peut changer.
◼ Par défaut, tous les conteneurs peuvent communiquer entre eux car ils sont créés dans le bridge .
◼ Il est possible de créer ses propres réseaux afin d’isoler les conteneurs entre eux.
◼ Les commandes utiles :
◼ docker network ls => liste les réseaux disponibles
◼ docker inspect monréseau => montre le détail du réseau nommé « monréseau »
◼ docker network create -d bridge –subnet 172.18.0.0/24 monréseau => créé le réseau 172.18.0.0/24 nommé
monréseau
LE RÉSEAU DANS DOCKER
◼ macvlan (bridge mode) - Connecté directement a notre réseau physique, un peu comme une VM - tu
peux lui attribuer une adresse de ton réseau local
◼ Donner son subnet local et gateway (box, routeur) et son parent (l'interface réseau de l'hôte) pour
mapper le reseau macvlan dessus
◼ Issue: Cela distribue une mac address au container et une interface réseau ne peux pas avoir plusieurs
mac sur une interface
◼ Il faut donc accepter le mode promiscuité
◼ ip link set eth0 promisc on
◼ et dans l'hyperviseur (workstation, esxi…)
◼ pas de dhcp - SPECIFIER UNE IP ADDRESS POUR LE CONTAINER POUR EVITER UN CONFLIT AVEC L'IP
DE L'HÔTE (VOIR DOC POUR LES OPTIONS AU DEPLOY)
MACVLAN (BRIDGE)
MACVLAN (802.1Q (TRUNKED))
◼ macvlan (802.1q mode) - Connecté directement a notre réseau physique, un peu comme une VM - tu peux lui
attribuer une adresse de ton réseau local, similaire à macvlan mais avec une notion de VLAN et de sous
interfaces.
◼ Réseau sous forme de vlan : - eth0.20 eth0.30 etc..
◼ Donner son subnet local et gateway (box) et son parent (l'interface réseau de l'hote avec .20 (num du vlan)
eg: eth0.20) pour la mapper dessus
◼ Ce réseau crée au hôte des sous interfaces
◼ docker network create -d macvlan \
◼ --subnet 192.168.20.0/24
◼ --gateway 192.168.20.1 \
◼ -o parent=eth0.20 \
◼ macvlan20
MACVLAN (802.1Q (TRUNKED))
IP VLAN (L2)
◼ Les container vont pouvoir avoir leur propre ip sur notre réseau local mais cette fois en partageant la mac
address de l'hôte
◼ docker network create -d ipvlan \
◼ --subnet 192.168.1.0/24
◼ --gateway 192.168.1.1 \
◼ -o parent=eth0 \
◼ new_ipvlan_network
◼ Explication :
◼ Lancer le conteneur nginx, le nommer monnginx, le laisser fonctionner. Rediriger son port 80 sur le 8080 de
notre machine locale
Lancez un premier premier container docker, l’image à utiliser devra être « nginx »
Vérifier si votre container est bien fonctionnel à l’aide de la commande « docker ps »
Stoppez votre container
Supprimez votre container et se rassurer qu’il a bien été supprimé.
Supprimer également les volumes qui auront été créé
TP 2 - LES IMAGES
Lancer le container Ubuntu en mode détaché et interactive avec un tag différent de latest
Que constatez vous?
Créez une nouvelle machine dans l’environnement de labs
Dans cette machine, lancez à nouveau le container ubuntu en mode interactive + nouveau terminal
Que constatez vous?
Supprimez les différents containers présent dans votre machine
Lancez le container Ubuntu en mode détaché avec la commande « sleep 4500 »
Utiliser la commande « docker exec » afin d’exécuter une commande à l’intérieur du container (commande de
création d’un dossier portant votre prénom »
Utiliser docker exec afin d’afficher l’ensemble des fichier et répertoire à l’aide de la commande « ls »
Utiliser docker exec et passez la commande « /bin/bash »
Que constatez vous?
Observez et expliquez le comportement de ces différentes commandes puis supprimez vos environnements
TP 4 - COMMANDES
◼ Lancer le container nginx en mode détaché et en exposant le port 80 du container sur le port 8080 de l’hote
◼ Vérifier le bon fonctionnement de votre container
◼ Vérifier qu’il est bien joignable à travers le port 8080 de votre hote.
◼ Que constatez vous? Quel est le contenu de la page web afficheé?
◼ A l’aide de docker exec, connectez vous à ce container afin de créer un fichier « index.html » dans lequel vous
feriez
◼ une briève présentation de vous
◼ Déplacer ce fichier index.html précédemment créé vers le répertoire « /usr/share/nginx/html» de votre
container
◼ Arrêtez votre container et redémarrez le à nouveau
◼ Essayez à nouveau d’y accéder à travers le port 8080 de votre hote… Que constatez vous?
TP – 6 : OPÉRATIONS ET INSPECTION D’UN CONTAINER
◼ Créez un fichier « index.html » en local sur votre machine contenant les mêmes informations que celui
du TP 5
◼ Lancez le container nginx en l’exposant sur le port 8080 et en ajoutant l’option (-v
./fichier_index.html:/usr/share/nginx/html//index.html)
◼ Vérifier que le container soit bien lancé
◼ Vérifiez que l’application de notre container nginx est bien consommable à partir du port 8080 de
notre hote
◼ Que constatez vous? Quel est le contenu de la page web afficheé?
◼ Supprimer les containers, images et votre environnement.
VARIABLES D’ENVIRONNEMENT
VARIABLES D’ENVIRONNEMENT EN PYTHON
from flask import Flask
from flask import render_template
import socket
import random
import os
import argparse
app = Flask(__name__)
color_codes = {
"red": "#e74c3c",
"green": "#16a085",
"blue": "#2980b9",
"blue2": "#30336b",
"pink": "#be2edd",
"darkblue": "#130f40"
}
SUPPORTED_COLORS = ",".join(color_codes.keys())
# Get color from Environment variable
COLOR_FROM_ENV = os.environ.get('APP_COLOR')
# Generate a random color
COLOR = random.choice(["red", "green", "blue", "blue2",
"darkblue", "pink"])
VARIABLES D’ENVIRONNEMENT
VARIABLES D’ENVIRONNEMENT DANS DOCKER
VARIABLES D’ENVIRONNEMENT
INSPECTER LES VARIABLES D’ENVIRONNEMENT
[
{
◼ docker inspect sweet_thompson "Id": "feeec06f67afb48834ea0854a9a8e849832eb7c8ebf3197f2759b96584f32680",
"Created": "2024-09-17T15:01:59.736801756Z",
"Path": "python",
"Args": [
"app.py"
],
"State": {
"Status": "running",
"Running": true,
[...]
},
[...]
"Name": "/sweet_thompson",
"RestartCount": 0,
"Driver": "overlay2",
"Platform": "linux",
[...]
},
[...]
},
"Mounts": [],
"Config": {
[...]
"APP_COLOR=green",
[...]
"Cmd": null,
"Image": "vlaine/webapp-color:amd64",
"Volumes": null,
"WorkingDir": "/opt",
"Entrypoint": [
"python",
"app.py"
],
"OnBuild": null,
"Labels": {}
TP – 7 : MANIPULATION VARIABLES D’ENVIRONNEMENT
◼ Lancez le container nginx en l’exposant sur le port 8080 et en ajoutant l’option (-v
./fichier_index.html:/usr/share/nginx/html//index.html)
◼ Lancez le container Ubuntu en mode détaché avec la commande « sleep 4500 »
◼ Utiliser la commande « docker exec » afin d’exécuter une commande à l’intérieur du container
(commande de création d’un dossier portant votre prénom »
◼ Utiliser docker exec afin d’afficher l’ensemble des fichier et répertoire à l’aide de la commande « ls »
◼ Utiliser docker exec et passez la commande « /bin/bash
◼ Lancez un container à partir de l’image vlaine/webapp-color:amd64 en exposant son port 8080 sur le
port 5000 de votre hôte
◼ Connectez vous sur le port 5000 de votre hôte afin de démarrer l’application
◼ Lancez à nouveau un autre container à base de la même image mais cette fois ci en définissant la
variable d’environnement APP_COLOR=red. (exposez sur le port 8000 )
◼ Run l’application. Que constatez vous?
◼ Supprimer votre environnement
DOCKER-COMPOSE
◼ Compose est un outil pour définir et exécuter des applications multi-conteneurs, aussi appelé "stack".
◼ Les conteneurs étant idéaux pour des applications basées sur des micro services, il devient évident que
rapidement on doit faire fasse à l’interconnexion de plusieurs conteneurs et à la gestion de multi-
conteneurs.
◼ Un fichier docker-compose s'écrit avec le langage YAML.
◼ Il se présentera sous la forme docker-compose.yml
◼ Références officiels : https://docs.docker.com/compose/reference/
◼ Il faut parfois l'installer, soit avec votre gestionnaire de paquet, soit avec curl :
◼ sudo curl -L "https://github.com/docker/compose/releases/download/1.23.2/docker-compose-$(uname -s)-
$(uname -m)" -o /usr/bin/docker-compose && sudo chmod +x /usr/bin/docker-compose
◼ Documentation d'installation : https://docs.docker.com/compose/install/#install-compose
DOCKER-COMPOSE
◼ Arguments de docker-compose !
◼ image qui permet de spécifier l'image source pour le conteneur ;
◼ build qui permet de spécifier le Dockerfile source pour créer l'image du conteneur ;
◼ volume qui permet de spécifier les points de montage entre le système hôte et les conteneurs ;
◼ restart qui permet de définir le comportement du conteneur en cas d'arrêt du processus ;
◼ environment qui permet de définir les variables d’environnement
◼ depends_on qui permet de dire que le conteneur dépend d'un autre conteneur ;
◼ ports qui permet de définir les ports disponibles entre la machine host et le conteneur.
DOCKER-COMPOSE
◼ Pour utiliser docker-compose, vous devez d'abord créer un fichier yml, ici quelques exemples de
docker-compose.yml version: "3"
services: services:
version: "3.9" # optional since v1.27.0 webapp: web:
services: image: examples/web image: "apache:${PHP_VERSION}"
web: restart: 'always'
build: .
ports: depends_on:
- mariadb
ports: - "8000:8000" ports:
- "8000:5000" volumes: - '8080:80'
links:
volumes: - .:/code - logvolume01:/var/log - "/data" - mariadb
depends_on: mariadb:
- redis image: "mariadb:${MARIADB_VERSION}"
restart: 'always'
redis: volumes:
image: redis - "/var/lib/mysql/data:${MARIADB_DATA_DIR}"
volumes: - "/var/lib/mysql/logs:${MARIADB_LOG_DIR}"
- /var/docker/mariadb/conf:/etc/mysql
logvolume01: {} environment:
MYSQL_ROOT_PASSWORD:
"${MYSQL_ROOT_PASSWORD}"
MYSQL_DATABASE: "${MYSQL_DATABASE}"
MYSQL_USER: "${MYSQL_USER}"
MYSQL_PASSWORD: "${MYSQL_PASSWORD}"
DOCKER-COMPOSE
version: '3'
services:
db:
image: mysql:5.7
volumes:
◼ Si par exemple vous voulez installer un wordpress - db_data:/var/lib/mysql
restart: always
avec docker-compose (en partant du principe que environment:
vous n'utilisez pas déjà l'image existante sur le hub MYSQL_ROOT_PASSWORD: somewordpress
MYSQL_DATABASE: wordpress
;) MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress
◼ Vous devrez installer une base de donnée et un
wordpress:
serveur web. depends_on:
- db
◼ docker-compose up -d image: wordpress:latest
ports:
- "8000:80"
◼ Puis http://127.0.0.1:8000 pour accéder à votre restart: always
wordpress environment:
WORDPRESS_DB_HOST: db:3306
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress
volumes:
db_data: {}
DOCKER COMPOSE - CHEAT SHEET
Commande Description
docker-compose up -d Démarre un ensemble de conteneurs en arrière-
plan
docker-compose down Stoppe un ensemble de conteneurs
docker-compose exec [service] [command] Exécute une commande au sein d'un service
docker-compose ps Affiche les stacks
docker-compose logs -f --tail 5 Afficher les logs du stack
docker-compose stop Arrêter un stack
docker-compose config Valider la syntaxe de votre fichier docker-compose
TP DOCKER-COMPOSE
◼ Fichiers de Surcharge
◼ L'idée générale est que vous aller faire votre compose complet avec toutes vos informations et si il se build
bien vous pourrez créer un compose de prod qui va simplement écraser certaines valeures pour les
remplacer et "alléger" la version prod. Exemple avec un service de base de donnée.
services:
postgres:
services:
image: postgres:13
container_name: postgres postgres:
environment: image: postgres:13-alpine
POSTGRES_USER: ${POSTGRES_USER:-$(cat /run/secrets/postgres_user)}
environment:
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-$(cat
/run/secrets/postgres_password)} PGDATA: /var/lib/postgresql/data/pgdata
POSTGRES_DB: ${POSTGRES_DB}
secrets:
- postgres_user
- postgres_password
volumes: # cat .env
- postgres-data:/var/lib/postgresql/data
- ./db/init.sql:/docker-entrypoint-initdb.d/init.sql POSTGRES_USER=admin
networks:
- todo-network
POSTGRES_PASSWORD=secret
healthcheck: # cat .env.prod
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
interval: 10s POSTGRES_USER=admin
timeout: 5s
retries: 5
POSTGRES_PASSWORD=supersecret
[…]
VARIABLES D'ENVIRONNEMENT ET INTERPOLATION
◼ DB_USER=${DB_USER:-default_user}
◼ Si DB_USER n'est pas défini, default_user sera utilisé.
DÉPENDANCES ET HEALTHCHECK
◼ Dépendances et Healthcheck
services:
web:
build: .
◼ depends_on spécifie l'ordre de démarrage
depends_on:
des services.
- db
◼ Ne vérifie pas l'état de santé du service, le db:
service peut avoir démarré mais ne pas être image: postgres
prêt.
healthcheck:
◼ Utiliser healthcheck pour vérifier si un test: ["CMD", "pg_isready", "-U", "postgres"]
service est prêt. interval: 10s
timeout: 5s
◼ Exemple d'un healthcheck :
retries: 3
◼ test: ['CMD', 'pg_isready -U postgres'] start_period: 30s
◼ interval: 30s, retries: 3
DÉPENDANCES ET HEALTHCHECK
services:
web:
build: .
depends_on:
- db
db:
image: postgres
healthcheck:
test: ["CMD", "pg_isready", "-U", "postgres"] #la commande à exécuter pour vérifier l'état.
interval: 10s #intervalle entre les vérifications.
timeout: 5s #temps maximal pour que la commande s'exécute.
retries: 3 #nombre de tentatives avant de considérer le service comme défaillant.
start_period: 30s #temps d'attente avant de commencer les vérifications.
GESTION DES SECRETS
secrets:
db_password:
file: ./secrets/db_password.txt
DOCKER IMAGES
◼ Rappel :
◼ container = plusieurs images/couches en lecture seul + couche Copy-On-Write + RUN
◼ IMAGES
◼ Chaque image est en lecture seule
◼ Partage des images entre containers sur le host
◼ Cache des couches de base en mémoire
c1 c2 c3 c4 c5 c6
app-a app-b app-c app-d app-e
websphere-liberty:8.5.5 websphere-liberty:beta c7 c8
= container
ibm-jre:8.0 mongo:latest
ubuntu:14.04 debian:wheezy = image
bootfs (Kernel)
DOCKER IMAGES - WORKFLOW D'UNE IMAGE
DOCKER IMAGES - WORKFLOW D'UNE IMAGE
• Lecture seule
• Réutilisation
• Couche (Layer)
DOCKER FILE
◼ Rappel :
◼ Docker file permet de créer une image
◼ FROM : Os de base Ubuntu / Alpine…
◼ Chaque commande créé une nouvelle couche
DOCKER FILE - CRÉER SON IMAGE
COMMENT CRÉER SA PROPRE IMAGE DOCKER
DOCKERFILE : ARCHITECTURE EN COUCHES
COMMENT CRÉER SA PROPRE IMAGE DOCKER
DOCKERBUILD : OUTPUT
DOCKERFILE - INSTRUCTIONS
1. FROM
8. ADD
1. Image parente
1. Ajoute un fichier dans l'image
2. LABEL
9. COPY
1. Ajout de métadonnées
1. Ajoute un fichier dans l'image
3. RUN
10. ENTRYPOINT
1. Commande(s) utilisée(s) pour construire l'image
1. Exécuter une commande au démarrage du conteneur
4. ENV
11. WORKDIR
1. Variable d'environnement
1. Permet de changer le chemin courant (cd tier)
5. CMD
12. VOLUME
1. Exécuter une commande au démarrage du conteneur
1. Crée un point de montage
6. EXPOSE
13. USER
1. Port(s) écouté(s) par le conteneur
1. Nom d'utilisateur ou UID à utiliser
7. ARG
14. ONBUILD
1. Variables passées comme paramètres à la construction de
l'image 1. Instructions exécutées lors de la construction d'images
enfants
COPY VS ADD
◼ COPY et ADD sont les deux instructions qui servent à des fins similaires. Ils vous permettent de copier des fichiers d'un
emplacement spécifique dans une image Docker.
◼ COPY prend un src et une destination . Il vous permet uniquement de copier dans un fichier ou un répertoire local de
votre hôte (la machine créant l'image Docker) dans l'image Docker elle-même.
◼ ADD vous permet de le faire aussi, mais il prend également en charge 2 autres sources. Tout d'abord, vous pouvez
utiliser une URL au lieu d'un fichier/répertoire local. Deuxièmement, vous pouvez extraire un fichier tar de la source
directement dans la destination.
◼ Dans la plupart des cas, si vous utilisez une URL, vous téléchargez un fichier zip et utilisez ensuite la RUN commande
pour l'extraire.
◼ Cependant, vous pouvez tout aussi bien utiliser RUN avec curl au lieu d' ADD afin de tout enchaîner en une seule RUN
pour créer une image Docker plus petite.
◼ Un cas d'utilisation valide pour ADD est lorsque vous souhaitez extraire un fichier tar local dans un répertoire
spécifique de votre image Docker. C'est exactement ce que fait l'image Alpine ADD rootfs.tar.gz / .
◼ Si vous copiez des fichiers locaux sur votre image Docker, utilisez toujours COPY car c'est plus explicite.
DOCKERFILE - CRÉER UNE IMAGE
◼ Un dockerfile est un fichier de configuration qui à pour objectif de créer une image.
◼ Nous y retrouverons une séquence d'instruction
◼ FROM : Sur quelle image on se base
◼ ENV : variables d'environnement
◼ EXPOSE : exposer le port du conteneur
◼ VOLUME : Définition des volumes
◼ COPY : cp entre host et conteneur
◼ ENTRYPOINT : processus maitre, car l'idée d'un conteneur est d'avoir un seul process qui tourne
DOCKERFILE - CRÉER UNE IMAGE
◼ L' intérêt d'un dockefile est de relancer une création d'image à tout moment
◼ Meilleure visibilité sur ce qui est fait
◼ Partage facile et possibilité de gitter
◼ Script d'édition de docker file (variables...)
◼ Ne pas se poser de question lors du docker run du conteneur
◼ Création images prod // dev - CI // CD (continuous integration/deployment)
DOCKERFILE - CRÉER UNE IMAGE
◼ FROM ubuntu:latest
◼ MAINTAINER vincent
◼ RUN apt-get update \
◼ && apt-get install -y vim git \
◼ && apt-get clean \
◼ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
◼ docker images
◼ Voir vos images
◼ Entrypoint est le processus principal sur lequel va tourner le conteneur qui va permettre de lancer l'image.
◼ CMD est la commande par défaut (arguments/paramètres par défaut)
◼ CMD seule remplace l'entrypoint
FROM alpine
MAINTAINER Vincent
CMD ["ping", "--help"]
◼ Mais ne prend pas les arguments passés en CLI.
◼ Si docker run --rm demo google.fr
◼ Vous aurez un message d'erreur car le CMD ne fera la distinction entre paramètre et process.
FROM alpine
MAINTAINER Vincent
ENTRYPOINT ["ping", "--help"]
◼ docker build -t demo -f Dockerfile .
◼ docker run --rm demo
◼ La commande passe puis en passant docker run --rm demo google.fr, vous ne chargerez pas le container.
DOCKERFILE : ENTRYPOINT VS CMD
FROM alpine
MAINTAINER Vincent
CMD ["--help"]
ENTRYPOINT ["ping"]
◼ docker build -t demo -f Dockerfile .
◼ docker run --rm demo google.fr
◼ La commande passe puis en passant docker run --rm demo google.fr.
◼ On précise le paramètre par défaut dans le CMD et le process dans le entrypoint !
TP : CRÉEZ VOTRE PREMIÈRE IMAGE
◼ Il s’agit ici de créer une image docker afin de conteneuriser une application web statique,
◼ Télécharger les fichiers de l’application à l’aide de git clone « https://github.com/sadofrazer/static-
website-example.git »
◼ conteneuriser cette application à l’aide de l’image de base nginx.
◼ Il s’agit ici de créer une image docker afin de conteneuriser une application web statique,
Faire une V2
◼ conteneuriser cette application sans télécharger les fichiers au préalable en local à l’aide de l’image de
base ubuntu.
◼ Fichiers de l’application se trouvant dans le repo : https://github.com/daviddias/static-webpage-
example.git
MEILLEURES PRATIQUES DANS LA CRÉATION DES IMAGES
◼ Points d’attention :
◼ Les conteneurs créés par l’image doivent être le plus « stateless » possible.
◼ Build context
◼ Use a .dockerignore file
◼ Use multi-stage builds
◼ Gestion des paquets
◼ Chaque conteneur doit avoir une utilité précise.
◼ Minimize the number of layers
◼ Sort multi-line arguments
◼ Build cache
BUILD CONTEXT
◼ Description :
◼ Lorsque l’on utilise la commande « docker build », le daemon docker créé un « context » qui contient tous les
fichiers et dossiers du répertoire contenant le fichier « Dockerfile ».
◼ Lors de la création de l’image, tous les dossiers et fichiers contenus dans le « build context » sont envoyés au
daemon docker, même si ils ne sont pas nécessaires à la création de l’image.
◼ Plus le « Build Context » est volumineux, plus la charge de travail du daemon docker pour créer l’image sera
importante !
◼ Meilleure pratique :
◼ Il est donc nécessaire de s’assurer que seuls les fichiers réellement indispensables à la création de l’image sont
dans le « Build Context ».
LE RÔLE DU DÉMON DOCKER
◼ Docker transfère les fichiers du build context vers le démon Docker dans un dossier temporaire.
◼ Plus le build context est volumineux, plus le transfert sera long.
◼ Utilisez .dockerignore pour exclure les fichiers inutiles et réduire la taille.
SPÉCIFIER LE CONTEXTE DE BUILD
◼ Docker met en cache chaque couche de build pour accélérer les reconstructions.
◼ Combinez des instructions RUN (ex : RUN apt update && apt install ...) pour éviter les problèmes de
cache.
◼ Placez les instructions COPY des fichiers changeants en fin de Dockerfile.
BUILD CACHE ET BONNES PRATIQUES
◼ Docker met en cache chaque couche de build pour accélérer les reconstructions.
◼ Combinez des instructions RUN (ex : RUN apt update && apt install ...) pour éviter les problèmes de
cache.
◼ Placez les instructions COPY des fichiers changeants en fin de Dockerfile.
◼ Cache valide : Si une couche est identique (même instruction, mêmes fichiers copiés), Docker la
réutilise directement, accélérant ainsi la construction.
◼ Cache invalidé : Si une instruction ou un fichier a changé, la couche et toutes celles qui la suivent sont
reconstruites.
BUILD CACHE ET BONNES PRATIQUES
◼ Si vous modifiez uniquement un fichier Python de votre application, seule la dernière couche (COPY . .)
sera reconstruite, les autres étant réutilisées du cache.
FROM python:3.9-slim-buster
WORKDIR /app
COPY . .
◼ Solution : le cache busting : Combinez les commandes en une seule instruction : RUN apt update && apt
install ....
◼ Ainsi, toute modification de la liste des paquets invalidera le cache et forcera la ré-exécution de apt update.
BONNES PRATIQUES : ORGANISEZ VOTRE DOCKERFILE
◼ Cache busting :
◼ Combinez les instructions liées, comme apt update && apt install, pour éviter les problèmes de cache.
◼ Triez les paquets par ordre alphabétique dans apt install pour faciliter la comparaison lors des reconstructions.
◼ Versions spécifiques :
◼ Fixez les versions des paquets (RUN pip3 install flask==2.0.2) pour éviter les changements inattendus liés aux
mises à jour.
BONNES PRATIQUES : ORGANISEZ VOTRE DOCKERFILE
FROM python:3.9-slim-buster
COPY . .
VS WORKDIR /app/
# occasionnellement
COPY requirements.txt requirements.txt COPY requirements.txt requirements.txt
RUN pip3 install -r requirements.txt RUN pip3 install -r requirements.txt --no-cache-dir
◼ Description:
◼ Le fichier caché « .dockerignore » doit être placé dans le même répertoire que le fichier « Dockerfile ».
◼ C’est l'équivalent d’un « .gitignore » pour Git.
◼ Il permet « d’ignorer » les fichiers présent dans le « context » qui ne sont pas nécessaire à la création de l’image.
◼ Ce fichier permet ainsi de créer les images plus rapidement et de diminuer la charge de travail envoyée au
daemon Docker.
GESTION DES PAQUETS
◼ Description :
◼ La gestion des paquets lors de la création des images est capitale pour diminuer la taille de l’image et pour
éviter les problèmes de paquets corrompus.
◼ Il faut installer dans l’image uniquement les paquets strictement nécessaires au bon fonctionnement de
l’application. Cela peut paraître évident, mais il n’est hélas pas rare de voir des images avec des paquets inutiles
!
◼ Une version doit systématiquement être indiquée pour chaque paquet à installer dans l’image pour éviter de
créer des images avec des paquets en version « latest » qui pourrait être corrompues, ou non supportés par
l’application les utilisant.
CHAQUE CONTENEUR DOIT AVOIR UNE UTILITÉ PRÉCISE.
◼ Description:
◼ Chaque conteneur doit avoir une fonctionnalité bien précise.
◼ Segmenter une application en plusieurs « processus » permet d’améliorer la scalabilité horizontale de
l’application et favorise la réutilisation des images de conteneurs.
GESTION DES COUCHES
◼ Description
◼ Docker stocke les images par layer.
◼ Si une même couche est présente sur différentes images, la couche n’est pas dupliquée sur le disque du node.
◼ En suivant ce principe de déduplication des couches en mémoire, il est recommandé de construire les images
dockers en ordonnant les couches, de la moins fréquemment changée à la plus fréquemment changée.
◼ Cela permet ainsi de drastiquement l’espace de disque utilisé par les images.
◼ Outils intéressant à prendre en compte pour gérer les couche : dive (téléchargeable en amont)
SORT MULTI-LINE ARGUMENTS
◼ Description :
◼ Lorsque c’est possible, arrangez le Dockerfile pour avoir les instructions
◼ les plus petites possible. Cela peut se faire en ayant recours au symbole « \ » avant de faire un retour à la ligne.
◼ Si vous devez installer plusieurs paquets, utilisez le « multi-ligne » pour installer tous les paquets par ordre
alphabétique avec une seule commande RUN.
◼ Cela permet de faciliter les mises à jour et les relectures du Dockerfile par la suite.
◼ Exemple :
BUILD CACHE
◼ Description :
◼ Par défaut, lors de la création d’une image, Docker vas chercher dans son cache local si il y a déjà des couches
utilisables pour la nouvelle image à construire.
◼ L’utilisation du cache d’image Docker permet de construire plus rapidement les images.
◼ Il est possible de désactiver l’utilisation du cache d’images docker en ajoutant l’argument « --no-cache=true » à la
commande « docker build ».
GÉRER LES VARIABLES AU SEIN DES IMAGES
◼ Objectifs:
◼ Il est parfois nécessaire de variabiliser les fichiers nécessaires à la création d’une image. (Par exemple pour
indiquer une base de données postgresql , ou un Bucket Amazon à une application).
◼ Cela permet de personnaliser des images Docker construites en se basant sur les mêmes fichiers source /
Dockerfile.
◼ La technique la plus utilisée est la suivante :
◼ Créer sur l’hôte docker des variables d’environnements.
◼ Appeler ces variables d’environnement dans les fichiers sources / Dockerfile via : ${VARIABLE}
◼ En général, ces variables d’environnement servent à définir les variables déclarées dans les
instructions « ENV » et « ARG » des Dockerfile.
OPTIMISATION DES IMAGES DOCKER
BASE IMAGE VS PARENT IMAGE DANS DOCKER
◼ Les termes Base Image et Parent Image dans Docker désignent les images utilisées dans un Dockerfile,
mais elles ont des rôles différents.
PARENT IMAGE
◼ Une Parent Image est l'image à partir de laquelle un Dockerfile commence. Exemple :
◼ FROM httpd
◼ httpd est une Parent Image, mais elle est elle-même basée sur Debian, qui est une autre Parent Image.
BASE IMAGE
◼ Une Base Image ne dérive d'aucune autre image. Elle est souvent créée from scratch, ce qui signifie
qu'elle part de zéro sans système d'exploitation.
FROM scratch
ADD rootfs.tar.xz /
DIFFÉRENCE ENTRE PARENT IMAGE ET BASE IMAGE
◼ Parent Image : Une image utilisée comme base dans un Dockerfile, mais qui dérive souvent d'une autre
image.
◼ Base Image : Une image construite à partir de scratch sans dépendance à d'autres images.
◼ Exemple : httpd est une Parent Image basée sur Debian, qui est une Base Image.
EXEMPLES CONCRETS
◼ MongoDB : Utilise Ubuntu comme Parent Image, qui est elle-même basée sur scratch.
◼ WordPress : Utilise PHP comme Parent Image, qui utilise Debian, basé sur scratch.
QU'EST-CE QUE L'IMAGE SCRATCH ?
◼ scratch est une image spéciale dans Docker, une image vide de base. Elle est utilisée pour créer des
systèmes minimaux, comme Debian.
◼ On part de zéro et on ajoute seulement les fichiers nécessaires.
CRÉATION D'UNE IMAGE À PARTIR DE SCRATCH
◼ Bien qu'il soit possible de partir de scratch, de nombreuses images minimales, comme Alpine ou
Debian, sont disponibles sur Docker Hub. Ces images sont optimisées pour être petites tout en étant
fonctionnelles.
RÉSUMÉ
◼ Parent Image : Image à partir de laquelle une autre image est construite, ex : httpd basé sur Debian.
◼ Base Image : Image qui ne dépend d'aucune autre image, ex : scratch.
◼ scratch : Image vide minimale utilisée pour créer des systèmes comme Debian.
BUILD MULTISTAGE
PRÉSENTATION
MULTI-STAGE BUILD
◼ Description :
◼ Le « multi-stage builds » est une nouvelle façon de construire les images de conteneurs applicatifs apportés avec
la version 17.05 de Docker.
◼ Cette technique est la plus puissante pour réduire drastiquement la taille d’une image docker.
◼ Le principe est d’utiliser un « Dockerfile » qui aura deux parties.
◼ La première partie déclare une image « intermédiaire » et qui sert à construire l’application.
◼ La deuxième partie déclare une image « minimaliste » (souvent from « scratch », qui est l’image la plus petite possible), et qui
exécute l’application compilée lors de la première partie.
◼ Il y a donc deux fois l’instruction « FROM » dans le Dockerfile.
◼ Au final on obtient une image minimaliste parfaitement fonctionnelle et ne contient que notre application.
BUILD MULTISTAGE
CAS D’UTILISATION
BUILD MULTISTAGE
EXEMPLE D’UTILISATION
DOCKERFILE – PACKAGING D’UNE APP- MULTI-STAGE BUILD
(TOUTES CES INSTRUCTIONS DANS UN DOCKERFILE)
◼ FROM alpine/git as clone ◼ Depuis l’image avec comme nom clone
◼ WORKDIR /app
◼ On va dans le dossier /app (répertoire de travail)
◼ RUN git clone https://github.com/XXXXXXXXXXXX
◼ On fait une git clone dans le workdir
◼ Utiliser le build multistage avec 3 stages afin de conteneuriser l’application précédente dans le but de
réduire la taille finale de notre image.
◼ Nous devons avoir 03 stages, le premier nous permettant de récupérer les fichiers source avec comme
base, le second stage nous permettant d’e build notre app à et le troisième de le deployer from scratch
◼ Tagger vos images
◼ Pushez les sur votre registry
TAG / PUSH / PULL
◼ Vous avez chargé un conteneur nginx qui s'appelle test01 par exemple.
◼ Vous avez deux images, ubuntu et nginx.
◼ Vous ajouter ensuite avec docker exec ce que vous souhaitez sur votre conteneur.
◼ exemple : apt install vim git dans votre conteneur
◼ Le but est de personnalisé et commiter le conteneur pour le transformer en image.
◼ L'inconvéniant c'est que si vous voulez recréer votre image vous serez obligé de tout refaire à la main a
contrario du dockerfile.
◼ docker ps, vous récupérez votre id
◼ Puis docker commit -m "Création de mon image" b676fr7qz6t7 vincent:v1.0
◼ Puis vérifier avec docker images, vous devrez la trouver
◼ docker run -tid --name imgvincent vincent:v1.0
◼ Le conteneur est créé, vous pouvez vous y connecter pour vérifier.
◼ docker history b676fr7qz6t7 pour voir les séquences déroulées dans notre création d'image.
CRÉER SA REGISTRY PRIVÉE
◼ Pour créer sa registry vous aurez besoin d'un certificat, de l'image associé, et de stockage.
openssl req -x509 -newkey rsa:4096 -nodes -keyout registryvlne.key -out registryvlne.crt -
days 365 -subj /CN=registry.vlne.fr
networks:
registry:
driver: bridge
CRÉER SA REGISTRY PRIVÉE
export DOCKER_HOST=tcp://192.168.1.100:2376
export DOCKER_TLS_VERIFY=1
export DOCKER_CERT_PATH=/path/to/certs
◼ Authentification par certificats :
◼ Configurer le fichier daemon.json avec l'option TLS verify pour vérifier les certificats clients.
◼ Générer des certificats pour les clients (client.pem et client-key.pem) et les partager de manière sécurisée
avec les machines clientes.
openssl req -newkey rsa:4096 -nodes -keyout client-key.pem -x509 -days 365 -out client-cert.pem -subj "/CN=client"
◼ Sur le client :
export DOCKER_TLS_VERIFY=1
export DOCKER_HOST=tcp://192.168.1.100:2376
export DOCKER_CERT_PATH=/path/to/certs
◼ Sécurisation de l'hôte Docker :
◼ Restreindre l'accès à l'hôte via SSH.
◼ Désactiver les ports inutiles.
◼ Accès externe au daemon Docker :
◼ Si nécessaire, ajouter l'option hosts dans le fichier daemon.json pour permettre l'accès via une IP privée.
◼ Sécurisation avec TLS :
◼ Utiliser tls et tlsverify dans le fichier daemon.json pour activer la communication chiffrée.
◼ Authentification par certificats :
{
"userns-remap": "username"
}
username : Le nom de l'utilisateur non privilégié sur l'hôte qui sera utilisé pour mapper les utilisateurs à
l'intérieur du conteneur.
User namespaces
◼ Si vous avez un utilisateur dockeruser sur votre système, vous pouvez le spécifier ainsi :
{
"userns-remap": "dockeruser"
}
User namespaces
Remappage vers un UID/GID spécifique
Créer un fichier de mappage :
◼ Vous pouvez créer un mappage d'utilisateur personnalisé dans /etc/subuid et /etc/subgid.
◼ Pour un utilisateur dockeruser, vous pourriez ajouter des lignes similaires à :
◼ /etc/subuid :
◼ dockeruser:100000:65536
◼ /etc/subgid :
◼ dockeruser:100000:65536
◼ dockeruser sur l'hôte est mappé aux UID allant de 100000 à 165536 dans les conteneurs.
Ensuite, dans daemon.json, vous spécifiez cet utilisateur pour le remappage :
{
"userns-remap": "dockeruser"
}
User namespaces
◼ Docker utilise les namespaces et les capacités Linux pour isoler les conteneurs et renforcer la sécurité.
◼ Namespaces : Fournissent une isolation en cloisonnant les ressources système.
◼ Capacités : Permettent de contrôler précisément les privilèges accordés aux processus.
◼ Meilleures pratiques :
◼ Exécuter les conteneurs avec des utilisateurs non-root.
◼ Limiter les privilèges en utilisant --cap-add et --cap-drop.
◼ Éviter l'utilisation du flag --privileged.
◼ Configurer les user namespaces pour une isolation supplémentaire.
INTRODUCTION AUX CGROUPS
◼ Les Cgroups (Control Groups) sont une fonctionnalité de Linux permettant d'allouer des ressources
telles que le CPU, la mémoire, et la bande passante réseau entre différents processus. Docker utilise les
Cgroups pour limiter les ressources entre différents conteneurs.
LIMITATION DES RESSOURCES CPU
◼ Par défaut, les conteneurs Docker n'ont aucune restriction sur la quantité de CPU qu'ils peuvent
utiliser.
◼ Les Cgroups permettent de contrôler l'utilisation des ressources CPU pour éviter qu'un conteneur ne
monopolise tout le CPU disponible.
COMMANDE NPROC
◼ Utilisez la commande nproc pour connaître le nombre de processeurs logiques disponibles sur votre
système:
◼ nproc
◼ La commande lscpu donne des informations détaillées sur le CPU, incluant le nombre de cœurs
physiques et logiques.
◼ lscpu
CPU(s): 4
Thread(s) per core: 2
Core(s) per socket: 2
Socket(s): 1
COMPRÉHENSION DU PARTAGE DU CPU
◼ Les processus peuvent partager le CPU en fonction des parts attribuées via les Cgroups.
◼ Un processus avec une part de 1024 recevra deux fois plus de temps CPU qu'un autre avec une part de
512.
LIMITATION DES RESSOURCES CPU AVEC DOCKER
◼ Utilisez l'option --cpu-shares pour définir les parts de CPU d'un conteneur.
◼ Exemple :
◼ Cela donne moins de temps CPU au conteneur 4 comparé à d'autres avec des parts plus élevées.
OPTIONS AVANCÉES : LIMITATION CPU
◼ Utilisez --cpuset-cpus pour définir des cœurs CPU spécifiques pour un conteneur.
◼ Exemple :
◼ Utilisez l'option --memory pour limiter la quantité de RAM utilisable par un conteneur.
◼ Exemple :
services:
webapp:
image: nginx database:
image: mysql
deploy:
environment:
resources: MYSQL_ROOT_PASSWORD: rootpassword
limits: deploy:
cpus: '0.5' # Limite à 50% d'un CPU resources:
memory: 512M # Limite la RAM à 512MB limits:
reservations: cpus: '1.0' # Limite à 1 CPU
cpus: '0.25' # Réserve 25% d'un CPU memory: 1G # Limite la RAM à 1GB
reservations:
pour garantir les performances minimales
cpus: '0.5' # Réserve 50% d'un CPU
memory: 256M # Réserve 256MB de RAM memory: 512M # Réserve 512MB de RAM
◼ docker run --rm -it progrium/stress --cpu 2 --io 1 --vm 2 --vm-bytes 128M --timeout
10s
◼ --cpu 2 : Charge le CPU en lançant 2 threads qui effectueront des calculs continus.
◼ --io 1 : Génère une charge I/O (entrées/sorties) en utilisant 1 thread.
◼ --vm 2 : Crée 2 processus de charge mémoire (allocation de mémoire virtuelle).
◼ --vm-bytes 128M : Chaque processus de charge mémoire alloue 128 Mo de mémoire.
◼ --timeout 10s : Le stress test s'exécutera pendant 10 secondes avant de s'arrêter automatiquement.
TP PRATIQUE : LIMITATION DES RESSOURCES