Conteneurisation des
applications
par
Sébastien FLEURY 1 / 51
Historique
2 / 51
Dans des temps anciens
●
Une application par serveur
3 / 51
Limitation des déploiements
●
Lenteurs de
déploiement
●
Serveurs coûtes chère
●
Ressources inutilisées
●
Difficile à multiplier
●
Difficile à migrer
●
Peut avoir des
limitations liées au
matériel
4 / 51
Arrivée de la virtualisation
●
Un serveur physique peut héberger plusieurs
applications
●
Chaque application s’exécute dans une
machine virtuelle
5 / 51
Avantage des machines virtuelles
●
Meilleure gestion des ressources
– Une machine physique héberge plusieurs
serveurs virtuelles
●
Faciliter à augmenter le nombre de machines
●
Plusieurs systèmes d’exploitation peuvent
cohabiter
●
Possibilité de migrer vers le Cloud
6 / 51
Inconvénients des VM
●
Chaque VM nécessite des ressources
– RAM
– CPU
– Stockage
– Un système d’exploitation
●
Plus il y a de VM, plus de ressource sont requises
●
La duplication des OS semble être inutile
●
La portabilité d’une application d’un OS à l’autre
n’est pas garantie
7 / 51
Qu’est ce qu’un conteneur
●
Empaquetage
d’applications
standardisée
●
Isolation des
applications entre
elles
●
Partagent le même
OS
8 / 51
Container vs VM
Les containers sont une structure au Les VM facilitent l’infrastructure de
niveau applicatif plusieurs services sur un serveur
9 / 51
VM + Container =
10 / 51
Bénéfices de Docker
●
Rapidité ●
Portabilité
– Moins de dépendances
– Aucun OS avec les librairies de l’hôte
– Démarre <secondes – Facilement déplaçable de
serveur
●
Efficacité
– Sans OS, moins d’espace consommé
– Densification des containers sur la machine
11 / 51
Nombreux serveurs et
environnements = complexité ?
12 / 51
Docker solutions
13 / 51
Passerelle du Dev à l’Ops
14 / 51
Le container dans la chaîne de
création logicielle
15 / 51
La technique de Docker
16 / 51
Terminologie
●
Image
– La base de docker, l’ensemble du contenu de l’application
●
Container
– Une image en cours d’exécution
●
Engine
– Le noyau applicatif du docker engine, gere le réseau, les volumes
●
Registry
– Service stockant et mettant à disposition les images
●
Control Plane
– Gestion du cluster applicatif
17 / 51
Registre, images et containers
18 / 51
User Story : Lancer mon premier
container
●
Installer docker
– https://docs.docker.com/engine/install/
●
https://hub.docker.com/_/hello-world
●
Découvrir les commandes dockers
– docker pull hello-world
– docker run hello-world
19 / 51
Les bases du Dockerfile
●
Les images dockers héritent d’une image de base
●
Une image se définie avec des commandes simples
– Exécuter une commande
– Ajouter un fichier ou répertoire
– Créer une variable d’environnement
– Définir le processus qui sera lancé au démarrage du container
●
Consiste en une série de couches utilisant le
UnionFileSystem, conservées dans le registre local
●
Lorsqu’une couche est modifiée les calques supérieurs
sont recalculés
20 / 51
Structure des containers
21 / 51
FROM
●
Définie l’image qui servira de base à la
définition de la nouvelle image
●
FROM node:16
●
FROM python:latest
●
FROM nginx
22 / 51
ENV
●
Permet de définir les variables
d’environnement qui seront utilisées par les
outils installées dans l’image
●
ENV TOMCAT_MAJOR 8
23 / 51
RUN
●
La commande RUN execute les commandes
dans une nouvelle couche de l’image et
valide le résultat. La couche suivante sera
basée sur celle ci.
●
RUN apt update && apt install -y bzr git \
mercurial \
subversion
24 / 51
ADD et COPY
●
ADD et COPY copient le contenu du PC vers
l’image
●
ADD désarchive les zip et accepte les URL
●
COPY se base sur le système de fichier de
l’hôte
– COPY ./ /app
– COPY package.json ./
25 / 51
WORKDIR
●
Définie le répertoire dans lequel se trouve le
système lorsqu’il execute les commandes qui
suivent (équivaut à cd /the/directory)
●
WORKDIR /app
26 / 51
EXPOSE
●
Définie le port qui sera ouvert sur le container
●
Il sera donc possible d’accéder à se
container par ce port
●
Une application doit écouter sur ce port
●
EXPOSE 3000
27 / 51
CMD
●
Définie la commande par défaut qui sera
exécutée au lancement du container
●
Pourra être surchargée au lancement du
container
●
CMD python app.py
28 / 51
Example de Dockerfile
FROM ubuntu:18.04
WORKDIR /app
COPY . ./
RUN make .
CMD python /app/app.py
29 / 51
Compiler son image
●
L’image sera stockée dans le registre local
●
Le fichier .dockerignore permet d’ignorer certains
fichiers pour optimiser les performances
●
Chaque instruction créée une nouvelle couche,
utilisation du cache de la couche précédente si
non invalidée
●
docker build . -t digitalseeder/myapp:v2
30 / 51
ry
t o
S User Story : Création d’un container web
er
Us
●
https://hub.docker.com/_/nginx
●
Creer un Dockerfile
●
Ajoutez y une page HTML que vous aurez créé
●
Construire son image
– docker build . -t myname/myproject
– docker build . -t digitalseeder/website
●
Executer son container et mapper les ports
●
Lancez plusieurs instances de cette image, il faudra
mapper des ports différents
31
ry
t o
S User Story : Déployer mon image sur Docker Hub
er
Us
●
Créez un compte dockerHub
●
Poussez votre image sur votre dépôt
●
Renommez votre image selon votre nom de repository
dockerhub
– Docker tag digitalseeder/myapp:v2 mydockerhubname/myrepositoryname:version
●
Connectez vous sur votre compte
– Docker login
●
Envoyez votre image
– Docker push mydockerhubname/myrepositoryname:version
●
Vérifiez que vous pouvez la récupérer
– Docker pull mydockerhubname/myrepositoryname:version
32
ry
t o
S User Story : Automatiser les releases sur Docker Hub
er
Us
1)Créez un fichier .gitlab-ci.yml pour définir vos tâches
CI/CD.
2)Ajoutez une tâche de build pour construire votre
image Docker.
3)Configurez les variables dans votre CI :
●
CI_REGISTRY_USER=VotreNomDUtilisateurDockerHub
●
CI_REGISTRY_PASSWORD=VotreMotDePasseDockerHub
●
CI_REGISTRY=docker.io
●
CI_REGISTRY_IMAGE=index.docker.io/VotreNomDUtilisateurDockerHub/VotreProjet
1) Ajoutez une tâche de déploiement, qui s'exécute
uniquement sur la branche "main".
33
Un mot sur les volumes
●
Connecter des Volumes : Les volumes Docker peuvent être associés à un espace
de stockage sur l'hôte, permettant ainsi aux conteneurs d'accéder à des données
persistantes.
●
Partage entre Conteneurs : Les volumes Docker peuvent être partagés entre
plusieurs conteneurs, facilitant le partage de données entre des applications
distinctes.
●
Persistance des Données : Par défaut, la suppression d'un conteneur ne supprime
pas le volume associé, garantissant la préservation des données persistantes.
●
Stockage Temporaire : Les données écrites dans un conteneur sont stockées
temporairement sur le système de fichiers de l'union (UFS) et sont perdues lorsque le
conteneur est supprimé.
Exemple de Commande pour lier le dossier local "./" au chemin "/app" dans le conteneur:
docker run myimage -v ./:/app
34 / 51
Gestion des Réseaux et de la
Connectivité
●
Configuration des Réseaux Docker :
– Les conteneurs Docker peuvent être configurés pour utiliser différents types de réseaux en fonction
des besoins de l'application : bridge, host, none, overlay (multi node – swarm, K8S).
– Les réseaux Docker permettent d'isoler les conteneurs les uns des autres, offrant un niveau de
sécurité et d'isolation.
docker network create mon_reseau
docker run --network=mon_reseau -d mon_conteneur
●
Liaison de Ports entre le Conteneur et l'Hôte :
– Par défaut, les ports des conteneurs ne sont pas exposés à l'extérieur.
– La liaison de ports (port mapping) permet de faire correspondre un port de l'hôte avec un port du
conteneur.
docker run -p 8080:80 mon_conteneur
●
Communication entre les Conteneurs :
– Docker permet aux conteneurs de communiquer entre eux au sein d'un même réseau.
– Les conteneurs peuvent se référer les uns aux autres par leur nom de conteneur ou leur nom de
service.
docker network create mon_reseau
docker run --network=mon_reseau --name conteneur1 -d mon_image1
docker run --network=mon_reseau --name conteneur2 -d mon_image2
35 / 51
Accès réseau
●
Les conteneurs Docker obtiennent des adresses IP différentes
à chaque démarrage, gérées par le moteur Docker lui-même.
●
L'attribution des adresses IP aux conteneurs est gérée
automatiquement par Docker Engine, ce qui rend difficile de
prédire à l'avance les adresses IP des conteneurs.
●
Pour simplifier l'accès aux conteneurs, il est courant de
rediriger un port de la machine hôte vers le conteneur.
Exemple :
Utilisation de la commande "docker run nginx -p 8080:80" où
8080 est le port de la machine hôte et 80 est le port du
conteneur.
36 / 51
Docker Compose en Bref
Orchestration simplifiée de plusieurs services
basés sur des images publiques (image) ou
construits localement (build)
Fichier de configuration docker-compose.yml.
Démarrage : docker-compose up.
Arrêt : docker-compose stop.
Suppression : docker-compose down.
Logs : docker-compose logs
nom_du_service.
Exécution de commandes : docker-
compose exec nom_du_service commande.
37 / 51
Docker compose dependencies
services:
server:
image: your_server_image
depends_on:
db:
condition: service_healthy
db:
image: your_db_image
healthcheck: test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost", "-uroot", "-ppass"]
test: "curl -f localhost:8080"
test: ... # Command to check health.
interval: 5s # Interval between health checks.
timeout: 5s # Timeout for each health checking.
retries: 20 # Hou many times retries.
start_period: 10s # Estimated time to boot.
38 / 51
ry
t o User Story : Création d’un service backend délivrant une API
S
r REST
e
Us
●
Clonez le template
– Git clone [email protected]:danielrohers/nodejs-express-api-scaffold.git backend
●
Ajoutez un Dockerfile (node:16-alpine), lancez yarn start
au démarrage
●
Créer un fichier docker-compose.yml
●
Définissez les services « api » et « mongo » et assurez
la résolution des noms en utilisant « links »
●
Testez l’accès à l’API depuis votre poste en mappant un
port local vers le container api
●
Ajoutez un volume persistant au container mongodb
39
ry
t o
S User Story : Container frontend
er
Us
●
Créer un projet ReactJS
– npx create-react-app frontend
●
Créer un Dockerfile pour embarquer
l’application
●
Faire évoluer le docker compose avec le
service frontend
●
Créer un composant React permettant de
récupérer le résultat d’une requête API
40
Exercices
41 / 51
Epopée des 3 jours
●
Comprendre Docker, son Dockerfile et
orchestrer avec docker-compose une
architecture multicontainers
●
Monter un projet multicontainers déclenchant
des scripts python interrogeant une base de
données Graph Neo4J
●
Présenter les rapports de projets
42 / 51
Epopée des 3 jours
●
Comprendre Docker, son Dockerfile et
orchestrer avec docker-compose une
architecture multicontainers
●
Monter un projet multicontainers déclenchant
des scripts python interrogeant une base de
données Graph Neo4J
●
Présenter les rapports de projets
43 / 51
Les bases de docker
●
Présentation générale sur slideshare
●
Installer Docker Engine
●
En ligne de commande
– docker pull [OPTIONS] NAME[:TAG|@DIGEST]
– docker run [OPTIONS] IMAGE[:TAG|@DIGEST] [COMMAND] [ARG…]
●
Lancer un hello world simple
– https://hub.docker.com/_/hello-world
●
Lancer un container avec montage de volume et mapping de port
– https://hub.docker.com/_/neo4j
●
Creer son Dockerfile, le pousser sur docker hub et récupérer celui
d’un camarade https://fr.slideshare.net/JeffreyEllin/dockerfile
●
Orchestrer avec docker-compose
44 / 51
Projet d’équipe
●
Créer un dépôt Git
●
Créer un container Neo4J
●
Container Python
Créer un script permettant l’import d’un CSV
dans un graph Neo4J FROM python:2.7
MAINTAINER Sebastien FLEURY
from flask import Flask "
[email protected]"
import os
COPY . /app
app = Flask(__name__)
WORKDIR /app
@app.route("/")
def hello():
RUN pip install -r requirements.txt
return "Flask inside Docker!!"
ENTRYPOINT ["python"]
if __name__ == "__main__": CMD ["app.py"]
port = int(os.environ.get("PORT", 5000))
app.run(debug=True,host='0.0.0.0',port=port) 45 / 51
Avancé
46 / 51
●
Only the instructions RUN, COPY, ADD create
layers. Other instructions create temporary
intermediate images, and do not increase the size
of the build.
●
Where possible, use multi-stage builds, and only
copy the artifacts you need into the final image.
This allows you to include tools and debug
information in your intermediate build stages
without increasing the size of the final image.
●
47 / 51
Multistage example
FROM golang:1.16 AS builder
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html
COPY app.go ./
RUN CGO_ENABLED=0 go build -a -installsuffix cgo -o app .
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /go/src/github.com/alexellis/href-counter/app ./
CMD ["./app"]
48 / 51
Cluster Swarm
●
Docker Swarm est un orchestrateur de
conteneurs intégré à Docker.
●
Il permet de gérer un cluster de nœuds
Docker comme une seule entité.
●
Il offre une haute disponibilité, la répartition
de charge et la gestion des conteneurs.
●
Il facilite le déploiement et la mise à l'échelle
des applications conteneurisées.
49 / 51
Utilisation de Docker Swarm
Créez un Cluster Swarm :
●
Commencez par créer un cluster Docker Swarm en ayant au moins un nœud manager et plusieurs nœuds
ouvriers.
●
Le nœud manager est responsable de la gestion du cluster et doit être initialisé en premier avec la commande
docker swarm init.
Ajoutez des Nœuds Ouvriers :
●
Pour agrandir le cluster, ajoutez des nœuds ouvriers avec la commande docker swarm join.
●
Les nœuds ouvriers exécutent les conteneurs et contribuent à la capacité de calcul du cluster.
Déployez des Services :
●
Utilisez la commande docker service create pour déployer des services, qui sont des ensembles de conteneurs.
●
Les services sont équilibrés automatiquement entre les nœuds du cluster, assurant la haute disponibilité.
Équilibrez la Charge :
●
Docker Swarm offre un équilibrage de charge intégré pour distribuer le trafic entre les conteneurs d'un service.
●
Il surveille la santé des conteneurs et réachemine le trafic en cas de panne.
Surveillance des Services :
●
Utilisez docker service ls pour afficher la liste des services déployés, leur état et le nombre de réplicas.
●
Cette commande permet de surveiller l'état global du cluster.
50 / 51
Expertise DevOps depuis
2016
51 / 51
www.digitalseeder.com