Docker
1. Introduction : Le lien entre LXC et Docker
1.1. Rappel des principes généraux de la conteneurisation
- Isolation des processus : Les conteneurs permettent de lancer des processus isolés sur un même noyau Linux. Chaque conteneur dispose de son propre espace de noms (namespace) et de ses propres ressources (cgroups) pour contrôler l'utilisation du CPU, de la mémoire, etc.
- Découplage du système hôte : Le système hôte n'est plus "pollué" par les dépendances, bibliothèques, applications installées dans un conteneur. Tout est empaqueté au sein du conteneur.
- Namespaces : Mécanisme du noyau Linux fournissant des espaces de noms indépendants pour les processus, l'interface réseau, les points de montage, l'UID, etc.
- cgroups : Mécanisme du noyau Linux permettant la limitation et la surveillance (contrôle) de l'utilisation des ressources (CPU, RAM, I/O).
1.2. LXC vs Docker : différence de philosophie
- LXC (Linux Containers) :
- Orienté "containers système".
- On peut y faire tourner un OS complet (par exemple un Ubuntu minimal) et se connecter en SSH pour administrer le conteneur comme une mini-machine virtuelle.
- Usage plus proche de la virtualisation traditionnelle, même si c'est plus léger qu'une VM.
- Docker :
- Orienté "containers applicatifs".
- Conçu pour exécuter rapidement des applications packagées dans des images légères.
- Favorise la philosophie "un processus par conteneur", en particulier dans les environnements de microservices et de CI/CD.
- Met en avant l'automatisation du cycle de vie des applications (build → ship → run) et l'utilisation de registres d'images (Docker Hub, registres privés, etc.).
En somme, Docker ne remplace pas LXC.
Docker s'est appuyé à l'origine sur LXC pour l'isolation de base (les mêmes briques du noyau Linux : namespaces, cgroups), mais propose une couche supplémentaire (Docker Engine, API, CLI, registry, système de build d'images, etc.) pour faciliter la création, le partage et le déploiement d'applications conteneurisées.
2. Qu'est-ce que Docker ?
2.1. Définition
Docker est une plateforme de conteneurisation qui permet de :
- Créer des images applicatives reproductibles et portables.
- Exécuter ces images sous forme de conteneurs isolés.
- Distribuer ces images via des registres (Docker Hub, registres privés, GitLab Container Registry, etc.).
2.2. Bénéfices clés
- Légèreté : Contrairement à une VM traditionnelle, un conteneur Docker ne contient pas le noyau complet ni l'OS complet, mais seulement les binaires et librairies nécessaires à l'application.
- Portabilité : Une image Docker peut être exécutée quasiment de la même manière sur n'importe quel hôte qui dispose de Docker (Linux, Windows, Mac, serveurs on-premises, cloud, etc.).
- Scalabilité : Facilite le déploiement, la mise à l'échelle (scale up/down) d'applications.
- Rapidité : Lancement des conteneurs en quelques millisecondes, contre plusieurs secondes (voire minutes) pour une VM classique.
- Isolément des dépendances : Chaque application embarque ses dépendances au sein de l'image, ce qui évite les conflits de versions ou les pollutions mutuelles.
3. Architecture de Docker
3.1. Les composants principaux
- Docker Engine (daemon) :
- Service qui tourne en arrière-plan.
- Gère les images, les conteneurs, les réseaux et les volumes.
- Écoute les requêtes de l'API Docker.
- Docker CLI (client) :
- Outil en ligne de commande (docker) permettant d'interagir avec le daemon.
- Envoie des requêtes à l'API REST de Docker Engine.
- Images Docker :
- Modèles en lecture seule qui décrivent comment construire un conteneur (system libraries, dépendances, configuration, fichier exécutable, etc.).
- Basées sur un système de fichiers en couches (UnionFS, OverlayFS, etc.).
- Conteneurs Docker :
- Instances en cours d'exécution d'images Docker.
- Sont isolés du système hôte grâce aux namespaces et cgroups.
- Registre Docker (Docker Hub, GitLab, Artifactory, etc.) :
- Permet de stocker et partager les images Docker.
- Public ou privé.
3.2. Cycle de vie basique
- Build : Construire une image à partir d'un Dockerfile ou en la téléchargeant d'un registre.
- Ship : Pousser l'image vers un registre, ou la récupérer depuis un registre.
- Run : Exécuter un conteneur à partir de cette image.
4. Installation de Docker (sur Linux, Windows, Mac)
4.1. Sur Linux
La méthode d'installation diffère selon la distribution (Debian, Ubuntu, CentOS, etc.). Généralement, on utilise les dépôts officiels Docker :
# Exemple pour Ubuntu
sudo apt-get update
sudo apt-get install \
ca-certificates \
curl \
gnupg \
lsb-release
# Ajouter la clé GPG officielle Docker
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
# Ajouter le dépôt Docker
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] \
https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Installer Docker
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
Ensuite, vérifier avec :
sudo systemctl status docker
docker version
docker info
4.2. Sur Windows / Mac
- Sur Windows :
- Docker Desktop pour Windows. Nécessite l'activation d'Hyper-V ou WSL2 (Windows Subsystem for Linux) selon la version de Windows.
- Docker Desktop embarque une VM Linux légère (via Hyper-V ou WSL2) qui fait tourner Docker Engine.
- Sur Mac :
- Docker Desktop pour Mac, similaire à Windows, intègre une petite VM Linux.
4.3. Permissions et configuration
- Par défaut, seul l'utilisateur root ou les membres du groupe docker peuvent lancer les commandes Docker.
- Si vous ne voulez pas utiliser sudo à chaque fois :
sudo usermod -aG docker $USER
- Il faudra ensuite se déconnecter / reconnecter pour que les changements soient effectifs.
5. Premiers pas avec Docker
5.1. Commandes de base
- docker pull : Télécharge une image depuis un registre (Docker Hub par défaut).
- docker run : Lance un conteneur à partir d'une image (ex. docker run hello-world).
- docker ps : Liste les conteneurs en cours d'exécution.
- docker ps -a : Liste tous les conteneurs (actifs et stoppés).
- docker stop : Arrête un conteneur.
- docker rm : Supprime un conteneur.
- docker rmi : Supprime une image.
- docker images : Liste les images disponibles localement.
- docker logs : Affiche les logs d'un conteneur.
- docker exec -it <container> bash : Lance un shell bash à l'intérieur du conteneur.
5.2. Exemple rapide
# Récupérer l'image 'hello-world'
docker pull hello-world
# Lancer un conteneur à partir de l'image
docker run hello-world
La commande docker run hello-world :
- Télécharge l'image hello-world si elle n'est pas encore présente localement.
- Lance un conteneur qui exécute un script s'affichant dans le terminal.
- Le conteneur s'arrête aussitôt le script terminé (d'où la philosophie "un conteneur = un processus").
6. Images Docker et Dockerfile
6.1. Création d'images via un Dockerfile
Le Dockerfile est un fichier texte décrivant la manière de construire votre image. Ex. :
# Choix de l'image de base
FROM ubuntu:20.04
# Variables d'environnement
ENV DEBIAN_FRONTEND=noninteractive
# Installation de paquets
RUN apt-get update && apt-get install -y \
python3 \
python3-pip
# Copie du code source
COPY app/ /app/
# Définition du répertoire de travail
WORKDIR /app
# Installation des dépendances Python
RUN pip3 install -r requirements.txt
# Définition du port d'écoute
EXPOSE 5000
# Commande de lancement par défaut
CMD ["python3", "app.py"]
6.2. Construction de l'image
# Dans le répertoire où se trouve le Dockerfile
docker build -t monimage:1.0 .
- L'option -t permet de nommer (tag) l'image (ex. monimage:1.0).
- Le . indique à Docker d'utiliser le Dockerfile dans le répertoire courant.
6.3. Inspection des images
- docker history <image> : Voir l'historique de construction (couches).
- docker inspect <image> : Voir les métadonnées de l'image (config, ID, etc.).
7. Gestion des conteneurs
7.1. Lancement et gestion du cycle de vie
- docker run -d : Lance un conteneur en mode détaché (en arrière-plan).
- docker run -p 8080:80 : Mappe le port 80 du conteneur sur le port 8080 de l'hôte.
- docker run -v /host/path:/container/path : Monte un répertoire (volume) du système hôte dans le conteneur.
- docker start/stop : Redémarre ou arrête un conteneur existant.
- docker restart : Redémarre un conteneur.
7.2. Networking de base
- Bridge par défaut : Tous les conteneurs sur le même hôte Docker peuvent communiquer via un bridge interne (généralement docker0).
- docker network create : Permet de créer des réseaux personnalisés (bridge, overlay, etc.).
- docker run --network mynetwork : Lance un conteneur sur un réseau spécifique.
8. Volumes Docker
8.1. Pourquoi utiliser des volumes ?
- Persister les données au-delà de la durée de vie d'un conteneur éphémère.
- Partager des données entre plusieurs conteneurs.
- Faciliter les sauvegardes/restaurations.
8.2. Création et utilisation
- docker volume create myvolume
- docker run -v myvolume:/data
Le répertoire /data dans le conteneur pointe vers le volume Docker myvolume.
8.3. Types de volumes
- Volumes gérés par Docker : Créés via docker volume create, stockés dans /var/lib/docker/volumes/.
- Bind mounts : Monte un répertoire de l'hôte dans le conteneur (-v /chemin/hôte:/chemin/conteneur).
- tmpfs : Montage en mémoire (RAM).
9. Docker Compose
9.1. Définition
Docker Compose est un outil qui permet de définir et d'exécuter des applications multi-conteneurs via un fichier docker-compose.yml. Il facilite :
- Le lancement simultané de plusieurs conteneurs (base de données, backend, frontend, etc.).
- La configuration de réseaux et de volumes partagés.
- L'exécution de commandes groupées (docker-compose up, docker-compose down, etc.).
9.2. Exemple de fichier docker-compose.yml
version: '3'
services:
web:
build: ./web
ports:
- "8080:80"
depends_on:
- db
db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: mydb
volumes:
- db_data:/var/lib/mysql
volumes:
db_data:
- Lancement : docker-compose up -d
- Arrêt : docker-compose down
10. Orchestration (Docker Swarm / Kubernetes)
10.1. Pourquoi l'orchestration ?
Quand on doit gérer plusieurs hôtes Docker, potentiellement distribués, il devient nécessaire de :
- Distribuer la charge de travail (load balancing).
- Garantir la haute disponibilité (HA).
- Faire du scaling automatique.
- Gérer la découverte de services.
10.2. Docker Swarm
- Orchestrateur intégré à Docker.
- Permet de créer un swarm (cluster) de plusieurs nœuds Docker.
- Commandes similaires à Docker classique, mais avec des notions de services, de modes "manager" et "worker".
10.3. Kubernetes
- Orchestrateur de conteneurs le plus répandu.
- Plus complet et plus complexe que Swarm.
- Utilise des Pods, des Services, des Ingress, des Deployments, etc.
- Souvent déployé dans les entreprises pour la production (on-premise, cloud, hybrides).
11. Intégration CI/CD
11.1. Pipeline typique
- Build : Construction de l'image Docker via un Dockerfile (ex. avec GitLab CI, Jenkins, GitHub Actions, etc.).
- Test : Lancement automatique de tests (unitaires, intégration, etc.) dans un conteneur.
- Push : Push de l'image validée dans un registre (Docker Hub, GitLab, Artifactory...).
- Deploy : Déploiement de l'image sur un environnement de production (ou staging) via Docker Compose, Swarm, Kubernetes, etc.
11.2. Avantages
- Standardisation du processus de build : même environnement de build sur toutes les plateformes.
- Fiabilité : Tests réalisés dans le même conteneur que celui qui sera déployé.
- Rapidité : Les pipelines exploitent la mise en cache des couches Docker.
12. Bonnes pratiques et sécurité
12.1. Bonnes pratiques de construction d'images
- Utiliser des images officielles ou maintenues, autant que possible.
- Minimiser la taille de l'image (multi-stage builds, images Alpine...).
- Nettoyer les caches et paquets inutiles (apt-get clean, rm -rf /var/lib/apt/lists/*) dans le Dockerfile.
- Éviter d'exécuter les processus en tant que root : utiliser un utilisateur dédié.
12.2. Sécurité
- Mettre à jour régulièrement Docker et les images pour éviter les vulnérabilités.
- Restreindre les capacités du conteneur (Docker --cap-drop).
- Utiliser des scanners de sécurité d'images (Trivy, Clair, etc.).
- Configurer correctement les firewalls et règles de réseau Docker.
12.3. Logging & Monitoring
- Externaliser les logs via des pilotes de logs Docker (journald, syslog, Elasticsearch, etc.).
- Surveiller la consommation en ressources des conteneurs.
- Utiliser des outils de supervision (Prometheus, Grafana...).
13. Cas d'usage sur votre infrastructure (Proxmox, Ceph, Hyper-V)
13.1. Docker sur Proxmox
- Vous pouvez exécuter Docker à l'intérieur de VMs tournant sur Proxmox, ou bien utiliser des conteneurs LXC comme "hôtes" Docker si la configuration le permet.
- Cependant, la configuration la plus standard est de créer une VM Linux (Debian, Ubuntu...) sur Proxmox et d'y installer Docker.
- Les données persistantes (volumes) peuvent être stockées sur le cluster Ceph pour assurer la haute disponibilité et la redondance.
13.2. Docker sur Hyper-V
- Sur Windows Server avec Hyper-V, vous pouvez également créer une machine virtuelle Linux, puis installer Docker.
- Docker Desktop pour Windows est plutôt destiné aux postes de développement, tandis qu'en production on privilégie un Linux dans une VM ou sur un bare-metal.
13.3. Avantages d'une approche conteneurisée
- Homogénéité entre les environnements LXC (Proxmox) et Docker : même logique d'isolation par le noyau Linux.
- Microservices : Si vous souhaitez découper votre application en services distincts, Docker Compose ou Kubernetes vous permettront une gestion fine de chaque service.
- CI/CD : Vous pouvez mettre en place des pipelines qui buildent automatiquement les images Docker dès qu'un commit est poussé sur votre dépôt de code.
14. Conclusion
Docker et LXC partagent les mêmes fondations (namespaces, cgroups) mais n'adressent pas le même usage. LXC se prête à l'exécution d'environnements "système" complets (un OS en mode conteneur), tandis que Docker est davantage centré sur les applications et les microservices.
Pour vous qui avez déjà découvert LXC, Docker est un complément incontournable pour :
- Automatiser le packaging et le déploiement d'applications.
- Accélérer la mise en place de pipelines CI/CD.
- Faciliter la gestion de configurations multi-conteneurs avec Docker Compose ou un orchestrateur.
Docker est un standard de facto dans le monde DevOps et le développement d'applications modernes.
Il leur offre une agilité et une portabilité remarquables, que ce soit en environnement de développement, de test ou de production.
Ressources complémentaires
N'hésitez pas à faire réaliser aux stagiaires des TP pratiques pour :
- Construire une image Docker simple (Dockerfile).
- Lancer l'application en local via docker run.
- Mettre en place un docker-compose.yml avec deux services (ex. un service web et une base de données).
- Explorer les logs, la persistance des données, la publication de l'image dans un registre privé, etc.