★ Formation DevOps — 3 jours — 21 heures

Maîtriser
Docker & Ansible

Pars de zéro et deviens opérationnel sur les technologies DevOps les plus demandées du marché.

12
Modules
40+
Exercices pratiques
21h
De contenu

Ce que tu vas apprendre

🐳
Docker & Conteneurs
Comprendre les conteneurs, images, volumes, réseaux
Débutant
🧩
Docker Compose
Orchestrer des apps multi-services avec un seul fichier
Intermédiaire
⚙️
Ansible
Automatiser la configuration de serveurs
Intermédiaire
🚀
Docker + Ansible
Déployer et gérer des conteneurs automatiquement
Avancé
💡 Méthode pédagogique

60% Pratique · 40% Théorie

Chaque leçon suit le même schéma : Concept → Analogie → Théorie → Exemple de code → Exercice pratique → Quiz. Tu ne lis pas — tu fais.

Avant de commencer :
le monde DevOps expliqué

Pose les bases conceptuelles pour comprendre pourquoi Docker et Ansible ont révolutionné l'informatique.

🤔
Le problème concret : Tu développes une application sur ton ordinateur. Ça marche parfaitement. Tu l'envoies à un collègue — ça plante. Lui dit "ça marche pas chez moi". Le fameux "works on my machine". Docker résout ça.

Qu'est-ce que le DevOps ?

DevOps = Development + Operations. C'est une culture et un ensemble d'outils pour que les développeurs et les équipes système travaillent ensemble pour livrer des applications rapidement et de façon fiable.

CI/CD
Intégration et déploiement continus — automatiser les tests et mises en production
Infrastructure as Code
Décrire ses serveurs dans des fichiers texte, comme du code source
Automatisation
Remplacer les tâches manuelles répétitives par des scripts ou outils
Conteneurisation
Emballer une app avec tout ce dont elle a besoin dans une boîte isolée
Orchestration
Gérer automatiquement plusieurs conteneurs à grande échelle
Idempotence
Exécuter la même action 1 ou 10 fois = même résultat. Clé d'Ansible.

La chaîne DevOps — vue d'ensemble

💻 Code 🧪 Tests CI 🐳 Docker Build 📦 Registry ⚙️ Ansible Deploy 🌐 Production

Dans cette formation, tu vas maîtriser les briques Docker Build, Registry et Ansible Deploy.

🐳 C'est quoi Docker, concrètement ?

Comprendre les conteneurs sans jargon, avec des analogies du monde réel.

🚢
L'analogie parfaite : Avant les conteneurs d'expédition (shipping containers), chaque cargaison avait une forme différente → chaos au port. Depuis les conteneurs standardisés, peu importe ce qu'il y a dedans — le bateau, la grue, le camion s'en foutent. Docker fait la même chose pour le logiciel.
Définition

Docker = une technologie de conteneurisation

Docker te permet d'emballer une application avec tout ce dont elle a besoin (code, dépendances, variables d'environnement, système de fichiers) dans une unité portable appelée conteneur. Ce conteneur tourne de façon identique partout.

VM vs Conteneur — La différence clé

Beaucoup confondent VM (machine virtuelle) et conteneur. Voici la différence visuelle :

Machine Virtuelle
App A
OS complet (Linux 2Go)
App B
OS complet (Linux 2Go)
Hyperviseur (VMware, VirtualBox...)
OS Hôte
Conteneurs Docker
App A (conteneur)
App B (conteneur)
Docker Engine
OS Hôte partagé
Matériel
VM
Démarre en minutes, plusieurs Go par instance, OS complet dupliqué
Conteneur
Démarre en secondes, quelques Mo, partage le noyau de l'hôte

Les composants de Docker

1

Docker Engine (le moteur)

Le programme qui tourne sur ta machine. Il gère tout : créer, lancer, arrêter des conteneurs.

2

Image Docker

Un modèle en lecture seule. Comme une recette de cuisine ou un plan d'architecte. Elle décrit ce que contiendra le conteneur.

3

Conteneur

Une instance en cours d'exécution d'une image. Comme un gâteau fabriqué à partir de la recette. Tu peux créer 50 conteneurs depuis la même image.

4

Docker Hub / Registry

Le dépôt d'images. Comme un GitHub, mais pour les images Docker. Des milliers d'images prêtes à l'emploi (Nginx, MySQL, Node.js...).

5

Dockerfile

Le fichier texte qui décrit comment construire ton image. Chaque ligne = une instruction de construction.

docker run
Lance un conteneur depuis une image
docker ps
Liste les conteneurs en cours d'exécution
docker pull
Télécharge une image depuis le registry
docker build
Construit une image depuis un Dockerfile
docker stop
Arrête un conteneur en cours d'exécution
docker rm
Supprime un conteneur arrêté
🧠 Question : Quelle est la différence entre une image Docker et un conteneur ?
✅ Parfait ! Comme une recette (image) vs le gâteau réel (conteneur). Tu peux faire 100 gâteaux avec la même recette.
❌ Pas tout à fait. L'image est le plan/modèle (statique, lecture seule). Le conteneur est la réalisation de ce plan, en cours d'exécution. Analogie : recette vs gâteau.

🔧 Installation de Docker

Installer Docker sur Linux, Mac ou Windows (WSL2).

ℹ️
Cette formation utilise Docker 26+. Les commandes modernes utilisent docker compose (sans tiret) au lieu de l'ancienne commande docker-compose.

Sur Linux (Ubuntu/Debian)

bash — terminal
# 1. Supprimer les anciens packages
sudo apt remove docker docker-engine docker.io containerd runc

# 2. Installer les dépendances
sudo apt update
sudo apt install ca-certificates curl gnupg

# 3. Ajouter la clé GPG officielle Docker
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

# 4. Ajouter le dépôt Docker
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 5. Installer Docker
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# 6. Vérifier l'installation
docker --version
# → Docker version 26.x.x

Sur Mac ou Windows

La façon la plus simple est d'installer Docker Desktop — une interface graphique qui inclut Docker Engine, Docker Compose, et un tableau de bord visuel.

💡
Sur Windows, active WSL2 (Windows Subsystem for Linux) avant d'installer Docker Desktop. Docker Desktop va détecter WSL2 automatiquement.

Vérifier que tout fonctionne

bash — premier test
# Lancer le conteneur de test officiel Docker
docker run hello-world

# Si tu vois "Hello from Docker!" → tout fonctionne !

# Vérifier la version
docker version

# Infos système
docker info

Ajouter ton utilisateur au groupe docker (Linux)

bash — éviter sudo à chaque commande
# Ajouter l'utilisateur courant au groupe docker
sudo usermod -aG docker $USER

# Déconnecter/reconnecter pour appliquer, puis tester sans sudo :
docker ps
🧪 TP Pratique

Lancer ton premier conteneur

Objectif : Lancer un serveur web Nginx en 30 secondes, accessible sur ton navigateur.
bash
# Lancer Nginx sur le port 8080
docker run -d -p 8080:80 --name mon-nginx nginx

# -d = détaché (en arrière-plan)
# -p 8080:80 = relier le port 8080 de ta machine au port 80 du conteneur
# --name = donner un nom au conteneur
# nginx = le nom de l'image à utiliser (téléchargée depuis Docker Hub)

# Ouvre http://localhost:8080 dans ton navigateur → page Nginx !

# Voir le conteneur tourner
docker ps

# Arrêter et supprimer
docker stop mon-nginx
docker rm mon-nginx

📦 Cycle de vie des conteneurs

Créer, inspecter, interagir et supprimer des conteneurs Docker.

Les états d'un conteneur

CREATED docker create start RUNNING docker run/start pause PAUSED docker pause stop STOPPED docker stop rm DELETED docker rm

Commandes essentielles

bash — gestion des conteneurs
=== LANCER ===
docker run nginx                         # Lance et s'attache (foreground)
docker run -d nginx                      # Lance en arrière-plan (detached)
docker run -it ubuntu bash               # Mode interactif (-i) avec terminal (-t)
docker run --name mon-app -d nginx       # Avec un nom personnalisé
docker run -p 8080:80 -d nginx           # Avec mapping de port
docker run -e MA_VAR=valeur -d nginx     # Avec variable d'environnement

=== VOIR ===
docker ps                                # Conteneurs en cours d'exécution
docker ps -a                             # Tous les conteneurs (même arrêtés)
docker logs mon-app                      # Voir les logs
docker logs -f mon-app                   # Logs en temps réel (follow)
docker inspect mon-app                   # Infos détaillées (JSON)
docker stats                             # Utilisation CPU/RAM en temps réel

=== INTERAGIR ===
docker exec -it mon-app bash             # Ouvrir un shell dans un conteneur actif
docker exec mon-app ls /app              # Lancer une commande sans entrer
docker cp fichier.txt mon-app:/tmp/      # Copier un fichier dans le conteneur

=== GÉRER ===
docker stop mon-app                      # Arrêt propre (SIGTERM)
docker kill mon-app                      # Arrêt forcé (SIGKILL)
docker restart mon-app                   # Redémarrer
docker rm mon-app                        # Supprimer (doit être arrêté)
docker rm -f mon-app                     # Supprimer de force
docker system prune                      # Nettoyer tout ce qui n'est pas utilisé
🧪 TP Pratique

Explorer un conteneur Ubuntu interactif

Objectif : Entrer dans un conteneur Ubuntu, installer un package, comprendre l'isolation.
bash
# Lancer Ubuntu en mode interactif
docker run -it ubuntu bash

# Tu es DANS le conteneur maintenant. Essaie :
cat /etc/os-release       # Version Ubuntu
ls /                      # Système de fichiers isolé
apt update && apt install -y curl
curl --version

# Quitter le conteneur
exit

# Sur ta machine hôte — curl n'est pas installé là :
# Les modifications dans un conteneur sont isolées !
docker ps -a              # Le conteneur est arrêté
docker rm $(docker ps -aq) # Tout nettoyer

🏗️ Images & Dockerfile

Créer tes propres images personnalisées avec un Dockerfile.

🍕
Analogie : Un Dockerfile, c'est la recette de cuisine. Chaque instruction est une étape. Docker "exécute" la recette et produit une image — le plat prêt à servir. Tu peux refaire le même plat (conteneur) autant de fois que tu veux.

Anatomie d'un Dockerfile

Dockerfile — application Node.js simple
# 1. Image de base (depuis Docker Hub)
FROM node:20-alpine

# 2. Métadonnées (optionnel mais bonne pratique)
LABEL maintainer="toi@exemple.com"

# 3. Répertoire de travail dans le conteneur
WORKDIR /app

# 4. Copier les fichiers de dépendances en premier (optimisation cache)
COPY package*.json ./

# 5. Installer les dépendances
RUN npm install

# 6. Copier le reste du code source
COPY . .

# 7. Exposer le port (documentation)
EXPOSE 3000

# 8. Variable d'environnement
ENV NODE_ENV=production

# 9. Commande de démarrage
CMD ["node", "server.js"]

Les instructions Dockerfile clés

FROM
Image de base. Toujours en premier. Ex: FROM ubuntu:22.04
RUN
Exécute une commande lors du build. Crée un nouveau layer.
COPY / ADD
Copie des fichiers depuis ton hôte vers l'image. COPY est préféré.
WORKDIR
Définit le répertoire courant pour les instructions suivantes.
EXPOSE
Documente le port. Ne publie PAS le port (ça c'est -p au run).
ENV
Définit une variable d'environnement accessible dans le conteneur.
CMD
Commande par défaut au démarrage. Remplaçable via docker run.
ENTRYPOINT
Commande fixe au démarrage. Plus stricte que CMD.
VOLUME
Crée un point de montage pour persister des données.
ARG
Variable disponible UNIQUEMENT au moment du build.

Construire et utiliser une image

bash — build et run
# Construire l'image depuis le répertoire courant (.)
docker build -t mon-app:1.0 .

# -t = tag (nom:version)
# . = contexte de build (répertoire courant)

# Lancer le conteneur
docker run -d -p 3000:3000 mon-app:1.0

# Voir les images disponibles
docker images

# Pousser sur Docker Hub
docker tag mon-app:1.0 tonusername/mon-app:1.0
docker push tonusername/mon-app:1.0

Multi-stage build — image légère

Les builds multi-étapes permettent de séparer l'environnement de build (avec tous les outils) de l'image finale légère pour la production.

Dockerfile — multi-stage (exemple Go)
# Étape 1 : Builder (image lourde avec les outils)
FROM golang:1.21 AS builder
WORKDIR /app
COPY . .
RUN go build -o main .

# Étape 2 : Image finale (ultra-légère)
FROM alpine:3.18
WORKDIR /app
COPY --from=builder /app/main .  # Copie uniquement le binaire compilé
CMD ["./main"]

# Résultat : image finale ~10 Mo au lieu de ~900 Mo !
🧠 Quelle instruction Dockerfile définit la commande qui s'exécute quand le conteneur démarre ?
✅ Exact ! CMD définit la commande par défaut. RUN s'exécute pendant le build de l'image (pas au démarrage). EXPOSE documente juste le port.
❌ RUN s'exécute lors du BUILD de l'image. EXPOSE documente juste le port. CMD (ou ENTRYPOINT) définit ce qui se passe au démarrage du conteneur.

💾 Persistance des données — Volumes

Par défaut, un conteneur perd toutes ses données quand il est supprimé. Les volumes résolvent ça.

🗄️
Analogie : Un conteneur sans volume, c'est comme travailler sur un document Word sans jamais sauvegarder. Tu fermes la fenêtre → tout est perdu. Un volume, c'est le disque dur externe branché au conteneur — les données survivent à la mort du conteneur.

Les 3 types de stockage

TypeSyntaxeCas d'usageGéré par
Named Volume-v monvolume:/dataBases de données, données persistantesDocker
Bind Mount-v /home/user:/appDev en temps réel, partage de configToi (système hôte)
tmpfs--tmpfs /tmpDonnées sensibles temporaires (RAM)Mémoire RAM

Named Volumes — La méthode recommandée

bash — gestion des volumes
# Créer un volume nommé
docker volume create mes-donnees

# Lancer MySQL avec un volume persistant
docker run -d \
  --name ma-bdd \
  -e MYSQL_ROOT_PASSWORD=secret \
  -e MYSQL_DATABASE=mabase \
  -v mes-donnees:/var/lib/mysql \
  mysql:8

# Même si tu fais "docker rm -f ma-bdd"...
# ...les données dans "mes-donnees" survivent !

# Lister les volumes
docker volume ls

# Inspecter un volume
docker volume inspect mes-donnees

# Supprimer un volume
docker volume rm mes-donnees

# Volume en lecture seule
docker run -v mon-config:/etc/config:ro mon-app

Bind Mounts — Pour le développement

bash — développement en temps réel
# Monter ton code source dans le conteneur
# Toute modification de fichier est immédiatement visible dans le conteneur
docker run -d \
  -p 3000:3000 \
  -v $(pwd):/app \               # $(pwd) = répertoire courant
  -v /app/node_modules \         # Exclure node_modules (trick !)
  mon-app:dev

# Maintenant, édite tes fichiers localement
# → le conteneur voit les changements en temps réel

🌐 Réseaux Docker

Faire communiquer des conteneurs entre eux de façon sécurisée.

🏘️
Analogie : Les réseaux Docker, c'est comme des quartiers privés. Les conteneurs dans le même quartier (réseau) peuvent se parler directement par leur nom. Les conteneurs de quartiers différents ne se voient pas, sauf si tu construis un pont (port binding).

Les drivers réseau

bridge (défaut)
Réseau privé isolé sur la machine hôte. Conteneurs communiquent par IP ou nom.
host
Le conteneur utilise directement le réseau de l'hôte. Pas d'isolation réseau.
none
Aucun réseau. Conteneur complètement isolé.
overlay
Réseau multi-hôtes. Utilisé avec Docker Swarm ou Kubernetes.

Créer et utiliser un réseau personnalisé

bash — réseau personnalisé
# Créer un réseau bridge personnalisé
docker network create mon-reseau

# Lancer une base de données dans ce réseau
docker run -d \
  --name ma-bdd \
  --network mon-reseau \
  -e POSTGRES_PASSWORD=secret \
  postgres:15

# Lancer une app qui doit parler à la BDD
docker run -d \
  --name mon-app \
  --network mon-reseau \
  -e DATABASE_URL=postgres://postgres:secret@ma-bdd:5432/db \
  mon-app:1.0

# ✅ mon-app peut accéder à ma-bdd en utilisant son nom "ma-bdd"
# Docker DNS résout automatiquement les noms des conteneurs

# Voir les réseaux
docker network ls

# Inspecter un réseau
docker network inspect mon-reseau

# Connecter un conteneur existant à un réseau
docker network connect mon-reseau autre-conteneur
💡
Dans un réseau personnalisé, les conteneurs peuvent se trouver par nom (DNS automatique). Dans le réseau bridge par défaut, tu dois utiliser les IPs.

🧩 Docker Compose

Orchestrer plusieurs conteneurs avec un seul fichier YAML.

🎼
Analogie : Docker Compose est le chef d'orchestre. Tu définis tous les musiciens (services), leurs instruments (images), leurs partitions (config) dans un seul fichier. Une commande et tout l'orchestre joue ensemble.
Concept

Un fichier, une application complète

Au lieu de lancer 5 commandes docker run avec des dizaines d'options, tu écris un fichier docker-compose.yml qui décrit toute ton application. docker compose up et tout démarre.

Exemple concret : App web + BDD + Cache

docker-compose.yml — stack complète
version: '3.9'

services:

  # Service 1 : Notre application web
  webapp:
    build: .                   # Build depuis le Dockerfile local
    ports:
      - "3000:3000"
    environment:
      - DATABASE_URL=postgres://user:pass@db:5432/mabase
      - REDIS_URL=redis://redis:6379
    depends_on:           # Attend que db et redis soient prêts
      - db
      - redis
    volumes:
      - ./:/app             # Bind mount pour le dev
    restart: unless-stopped

  # Service 2 : Base de données PostgreSQL
  db:
    image: postgres:15-alpine
    environment:
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=pass
      - POSTGRES_DB=mabase
    volumes:
      - postgres-data:/var/lib/postgresql/data
    ports:
      - "5432:5432"          # Exposer pour debug local

  # Service 3 : Cache Redis
  redis:
    image: redis:7-alpine
    ports:
      - "6379:6379"

volumes:
  postgres-data:          # Volume nommé géré par Docker

Commandes Docker Compose

bash — gestion avec Compose
# Démarrer tous les services (build si nécessaire)
docker compose up

# Démarrer en arrière-plan
docker compose up -d

# Rebuild les images et démarrer
docker compose up --build

# Voir l'état des services
docker compose ps

# Voir les logs de tous les services
docker compose logs

# Logs d'un service en particulier, en temps réel
docker compose logs -f webapp

# Entrer dans un conteneur d'un service
docker compose exec webapp bash

# Lancer une commande dans un service
docker compose exec db psql -U user -d mabase

# Arrêter les services (sans supprimer les volumes)
docker compose stop

# Arrêter ET supprimer conteneurs + réseau
docker compose down

# Arrêter + supprimer volumes (⚠️ perte de données !)
docker compose down -v

# Scaler un service (ex: 3 instances de webapp)
docker compose up --scale webapp=3
🧪 TP Pratique

Stack WordPress en 5 minutes

Objectif : Lancer un WordPress complet avec MySQL, accessible sur http://localhost:8080
docker-compose.yml — WordPress + MySQL
version: '3.9'
services:
  wordpress:
    image: wordpress:latest
    ports:
      - "8080:80"
    environment:
      - WORDPRESS_DB_HOST=db
      - WORDPRESS_DB_USER=wp
      - WORDPRESS_DB_PASSWORD=secret
      - WORDPRESS_DB_NAME=wordpress
    depends_on:
      - db
  db:
    image: mysql:8
    environment:
      - MYSQL_DATABASE=wordpress
      - MYSQL_USER=wp
      - MYSQL_PASSWORD=secret
      - MYSQL_ROOT_PASSWORD=rootsecret
    volumes:
      - mysql-data:/var/lib/mysql
volumes:
  mysql-data:

---
# Puis dans ton terminal :
# docker compose up -d
# Ouvre http://localhost:8080
⚙️

Partie 2 : Ansible

Automatiser la configuration et le déploiement sur des serveurs distants

Automatisation Infrastructure as Code Sans agent

⚙️ C'est quoi Ansible ?

Comprendre l'automatisation de configuration sans jargon.

📋
Analogie : Imagine que tu dois configurer 50 serveurs identiques. Sans Ansible : tu te connectes sur chacun en SSH et tu tapes les mêmes commandes 50 fois (3 heures de travail et des erreurs inévitables). Avec Ansible : tu écris ta "liste d'instructions" une fois, tu lances une commande → les 50 serveurs sont configurés en 5 minutes, de façon identique.
Définition

Ansible = Automatisation déclarative via SSH

Ansible est un outil d'automatisation IT qui te permet de décrire l'état désiré de tes serveurs dans des fichiers YAML appelés playbooks. Il se connecte via SSH (pas d'agent à installer) et applique les changements nécessaires.

Déclaratif vs Impératif — Concept fondamental

ApprocheTu décris...Exemple
Impératif (scripts bash)les ÉTAPES à suivre"apt-get install nginx, puis cp fichier.conf, puis systemctl start nginx"
Déclaratif (Ansible)l'ÉTAT final voulu"Je veux que nginx soit installé, configuré avec ce fichier, et démarré"
💡
Idempotence : En Ansible, tu peux relancer le même playbook 10 fois. Si nginx est déjà installé, il ne le réinstalle pas. Résultat toujours identique. C'est la grande force.

Architecture Ansible

1

Control Node (ta machine)

La machine où Ansible est installé. C'est d'ici que tu lances tes playbooks. Nécessite Python et Linux/Mac (ou WSL sous Windows).

2

Managed Nodes (tes serveurs)

Les machines que tu veux configurer. Besoin uniquement de SSH et Python. Aucun agent à installer.

3

Inventaire

Fichier listant tes serveurs. Qui est où, dans quel groupe.

4

Playbook

Fichier YAML décrivant ce qu'Ansible doit faire. Composé de "plays" qui contiennent des "tasks".

5

Module

Unité d'action réutilisable. Ex: apt pour installer des packages, copy pour copier des fichiers, service pour gérer des services.

Installation d'Ansible

bash — installation
# Sur Ubuntu/Debian
sudo apt update
sudo apt install python3-pip
pip3 install ansible

# Vérifier la version
ansible --version
# → ansible [core 2.18.x]

# Premier test : ping sur ta propre machine
ansible localhost -m ping
# → localhost | SUCCESS => { "ping": "pong" }
🧠 Quel est l'avantage principal d'Ansible par rapport à un script bash ?
✅ Parfait ! L'idempotence est la clé. Un script bash peut échouer si nginx est déjà installé. Ansible s'adapte à l'état actuel et ne fait que ce qui est nécessaire.
❌ La vraie force d'Ansible est l'idempotence (relancer = même résultat) et l'approche déclarative (décrire l'état voulu, pas les étapes). Ansible utilise SSH et est écrit en Python.

📋 Les Inventaires Ansible

Décrire et organiser tes serveurs dans des groupes logiques.

Concept

L'inventaire = le carnet d'adresses de tes serveurs

L'inventaire liste toutes les machines que tu veux gérer avec Ansible. Tu peux les organiser en groupes (webservers, databases, production, staging...) et définir des variables par groupe ou par hôte.

Format INI (simple)

inventaire/hosts — format INI
# Hôtes standalone
192.168.1.10
mon-serveur.exemple.com

# Groupe "webservers"
[webservers]
web1.exemple.com
web2.exemple.com  ansible_port=2222   # Port SSH custom
web3              ansible_host=192.168.1.20

# Groupe "databases"
[databases]
db1.exemple.com
db2.exemple.com

# Groupe contenant d'autres groupes
[production:children]
webservers
databases

# Variables pour un groupe
[webservers:vars]
ansible_user=ubuntu
ansible_ssh_private_key_file=~/.ssh/ma-cle

Format YAML (recommandé pour les gros projets)

inventaire/hosts.yml — format YAML
all:
  children:
    webservers:
      hosts:
        web1:
          ansible_host: 192.168.1.10
          ansible_user: ubuntu
        web2:
          ansible_host: 192.168.1.11
          ansible_user: ubuntu
      vars:
        http_port: 80
        max_clients: 200
    databases:
      hosts:
        db1:
          ansible_host: 192.168.1.20
          ansible_user: admin

Tester son inventaire

bash — vérifications
# Lister tous les hôtes de l'inventaire
ansible all -i inventaire/hosts --list-hosts

# Lister uniquement le groupe webservers
ansible webservers -i inventaire/hosts --list-hosts

# Ping tous les serveurs
ansible all -i inventaire/hosts -m ping

# Commande ad-hoc : voir l'uptime de tous les webservers
ansible webservers -i inventaire/hosts -m command -a "uptime"

# Commande shell (avec pipes, redirections...)
ansible all -i inventaire/hosts -m shell -a "df -h | grep /dev/sda"

📜 Playbooks Ansible

Écrire des scénarios d'automatisation en YAML.

🎬
Analogie : Un playbook, c'est le scénario d'un film. Il y a des scènes (plays), dans chaque scène des acteurs (hosts), et chaque acteur a des actions à faire (tasks). Ansible exécute ce scénario sur tes serveurs.

Structure d'un playbook

playbook.yml — structure complète
---
# Un playbook = liste de "plays"

- name: Configurer les serveurs web     # Nom du play
  hosts: webservers                     # Sur quel groupe agir
  become: true                          # Devenir root (sudo)
  vars:                                 # Variables locales
    nginx_port: 80
    app_name: monapp

  tasks:                               # Liste des tâches

    - name: Mettre à jour les packages
      apt:
        update_cache: true
        upgrade: dist

    - name: Installer Nginx
      apt:
        name: nginx
        state: present         # present = installé, absent = désinstallé

    - name: Copier la config Nginx
      copy:
        src: files/nginx.conf
        dest: /etc/nginx/nginx.conf
        owner: root
        group: root
        mode: '0644'
      notify: Redémarrer Nginx   # Déclenche le handler si modifié

    - name: Démarrer et activer Nginx
      service:
        name: nginx
        state: started
        enabled: true           # Démarrer au boot

    - name: Créer un utilisateur app
      user:
        name: "{{ app_name }}"    # Utiliser une variable
        shell: /bin/bash
        create_home: true

    - name: Tâche conditionnelle
      debug:
        msg: "Nous sommes sur Ubuntu"
      when: ansible_distribution == "Ubuntu"

  handlers:                           # Tâches déclenchées par notify
    - name: Redémarrer Nginx
      service:
        name: nginx
        state: restarted

Modules Ansible les plus utilisés

apt / yum / dnf
Gestion de packages (install, remove, update)
copy / template
Copier des fichiers. template = avec variables Jinja2
service / systemd
Gérer des services (start, stop, enable)
user / group
Créer/modifier des utilisateurs et groupes
file
Créer/supprimer fichiers, dossiers, liens symboliques
command / shell
Exécuter des commandes. shell supporte pipes/redirections
git
Cloner/mettre à jour des dépôts Git
debug
Afficher des messages ou valeurs de variables
register / set_fact
Capturer le résultat d'une tâche dans une variable
loop / with_items
Répéter une tâche sur une liste d'éléments

Lancer un playbook

bash — exécution de playbooks
# Lancer le playbook
ansible-playbook -i inventaire/hosts playbook.yml

# Mode dry-run (voir ce qui serait fait sans rien changer)
ansible-playbook -i hosts playbook.yml --check

# Mode verbose (voir le détail des actions)
ansible-playbook -i hosts playbook.yml -v
ansible-playbook -i hosts playbook.yml -vvv    # Très verbeux

# Cibler un sous-ensemble
ansible-playbook -i hosts playbook.yml --limit web1

# Demander le mot de passe sudo
ansible-playbook -i hosts playbook.yml --ask-become-pass

# Démarrer depuis une tâche précise
ansible-playbook -i hosts playbook.yml --start-at-task "Installer Nginx"
🧪 TP Pratique

Playbook : Installer un serveur web complet

Objectif : Créer un playbook qui installe Nginx, déploie une page HTML et ouvre le firewall.
setup-webserver.yml
---
- name: Déployer un serveur web
  hosts: webservers
  become: true

  tasks:
    - name: Installer Nginx et UFW
      apt:
        name:
          - nginx
          - ufw
        state: present
        update_cache: true

    - name: Déployer page d'accueil
      copy:
        content: "<h1>Déployé par Ansible !</h1>"
        dest: /var/www/html/index.html

    - name: Ouvrir le port 80
      ufw:
        rule: allow
        port: '80'

    - name: S'assurer que Nginx tourne
      service:
        name: nginx
        state: started
        enabled: true

🔐 Ansible Vault — Gérer les secrets

Chiffrer les mots de passe et données sensibles dans tes playbooks.

⚠️
Danger : Ne jamais commiter des mots de passe en clair dans Git. Ansible Vault chiffre tes secrets avec AES-256.
Concept

Vault = coffre-fort chiffré pour tes variables sensibles

Ansible Vault chiffre des fichiers de variables (ou des valeurs individuelles) avec un mot de passe maître. Le fichier chiffré peut être commité dans Git sans risque.

bash — utilisation de Vault
=== CRÉER / CHIFFRER ===
# Créer un fichier de secrets chiffré
ansible-vault create secrets.yml
# → Demande un mot de passe maître, ouvre un éditeur

# Chiffrer un fichier existant
ansible-vault encrypt vars/passwords.yml

# Chiffrer une seule valeur (inline)
ansible-vault encrypt_string 'mon-super-mdp' --name 'db_password'
# → Génère une valeur chiffrée à coller dans ton YAML

=== VOIR / MODIFIER ===
# Voir le contenu chiffré
ansible-vault view secrets.yml

# Éditer le contenu
ansible-vault edit secrets.yml

# Déchiffrer (attention !)
ansible-vault decrypt secrets.yml

=== UTILISER DANS UN PLAYBOOK ===
# Lancer un playbook avec les secrets
ansible-playbook -i hosts playbook.yml --ask-vault-pass

# Ou avec un fichier mot de passe (pratique en CI/CD)
echo "mon-mot-de-passe" > .vault_pass
chmod 600 .vault_pass
ansible-playbook -i hosts playbook.yml --vault-password-file .vault_pass

Exemple — Playbook avec variables chiffrées

vars/secrets.yml — contenu avant chiffrement
# Ce fichier sera chiffré par ansible-vault
db_password: MonMotDePasse123!
api_key: sk-abc123def456
jwt_secret: supersecretkey
deploy.yml — utilisation des secrets
---
- name: Déployer l'application
  hosts: all
  vars_files:
    - vars/secrets.yml      # Fichier chiffré — déchiffré automatiquement

  tasks:
    - name: Configurer la BDD
      template:
        src: templates/db.conf.j2
        dest: /etc/app/db.conf
      # Dans le template : {{ db_password }}

🚀 Docker + Ansible — La combinaison ultime

Automatiser le déploiement et la gestion de conteneurs Docker avec Ansible.

🏭
Synergie : Docker emballe ton application de façon portable. Ansible automatise l'installation de Docker sur tes serveurs ET le déploiement de tes conteneurs. Ensemble : une application déployée partout, en un clic.

Le module community.docker

bash — installer la collection Docker
# Installer la collection Ansible pour Docker
ansible-galaxy collection install community.docker

# Vérifier l'installation
ansible-galaxy collection list | grep docker

Playbook complet : Installer Docker + Déployer une app

deploy-docker.yml — playbook production
---
- name: Installer Docker sur les serveurs
  hosts: all
  become: true

  tasks:
    - name: Installer les dépendances
      apt:
        name: [ca-certificates, curl, gnupg]
        state: present
        update_cache: true

    - name: Ajouter la clé GPG Docker
      apt_key:
        url: https://download.docker.com/linux/ubuntu/gpg
        state: present

    - name: Ajouter le dépôt Docker
      apt_repository:
        repo: "deb https://download.docker.com/linux/ubuntu {{ ansible_lsb.codename }} stable"
        state: present

    - name: Installer Docker
      apt:
        name: [docker-ce, docker-ce-cli, containerd.io, docker-compose-plugin]
        state: present

    - name: Démarrer Docker
      service:
        name: docker
        state: started
        enabled: true

    - name: Ajouter l'utilisateur au groupe docker
      user:
        name: "{{ ansible_user }}"
        groups: docker
        append: true

- name: Déployer l'application
  hosts: webservers
  become: true

  tasks:
    - name: Créer le réseau Docker
      community.docker.docker_network:
        name: app-network
        state: present

    - name: Lancer le conteneur PostgreSQL
      community.docker.docker_container:
        name: postgres
        image: postgres:15-alpine
        state: started
        restart_policy: unless-stopped
        networks:
          - name: app-network
        env:
          POSTGRES_PASSWORD: "{{ db_password }}"  # depuis Vault !
          POSTGRES_DB: mabase
        volumes:
          - postgres-data:/var/lib/postgresql/data

    - name: Lancer le conteneur de l'application
      community.docker.docker_container:
        name: webapp
        image: monusername/webapp:latest
        state: started
        restart_policy: unless-stopped
        ports:
          - "80:3000"
        networks:
          - name: app-network
        env:
          DATABASE_URL: "postgres://postgres:{{ db_password }}@postgres:5432/mabase"

    - name: Vérifier que les conteneurs tournent
      community.docker.docker_container_info:
        name: webapp
      register: container_info

    - name: Afficher le statut
      debug:
        msg: "Conteneur webapp : {{ container_info.container.State.Status }}"
🏆
Ce playbook représente le niveau production : Docker installé automatiquement, conteneurs déployés, secrets chiffrés via Vault, vérification de l'état. C'est ce que font les DevOps chaque jour.

📖 Glossaire complet & Cheat Sheet

Tous les mots clés, commandes et concepts en un seul endroit.

🐳 Commandes Docker essentielles

Docker Cheat Sheet
=== CONTENEURS ===
docker run -d -p 8080:80 --name app nginx   # Lancer
docker ps                                    # Lister actifs
docker ps -a                                 # Lister tous
docker stop/start/restart app               # Contrôle
docker rm -f app                             # Supprimer
docker exec -it app bash                     # Shell interactif
docker logs -f app                           # Logs en direct
docker stats                                 # Monitoring
docker inspect app                           # Détails JSON

=== IMAGES ===
docker build -t app:1.0 .                   # Construire
docker images                                # Lister
docker pull nginx:alpine                     # Télécharger
docker push user/app:1.0                     # Pousser vers registry
docker rmi app:1.0                           # Supprimer
docker image prune                           # Nettoyer inutilisées

=== VOLUMES ===
docker volume create monvol                 # Créer
docker volume ls                             # Lister
docker volume rm monvol                      # Supprimer
docker run -v monvol:/data app              # Named volume
docker run -v $(pwd):/app app               # Bind mount

=== RÉSEAUX ===
docker network create mon-net               # Créer
docker network ls                            # Lister
docker run --network mon-net app            # Connecter
docker network inspect mon-net              # Inspecter

=== COMPOSE ===
docker compose up -d                        # Démarrer tout
docker compose down                          # Arrêter tout
docker compose ps                            # État des services
docker compose logs -f service              # Logs d'un service
docker compose exec service bash           # Shell dans service
docker compose pull                          # Mettre à jour images

=== NETTOYAGE ===
docker system prune                          # Tout nettoyer
docker system prune -a --volumes            # Nettoyage complet

⚙️ Commandes Ansible essentielles

Ansible Cheat Sheet
=== AD-HOC ===
ansible all -i hosts -m ping                # Test connectivité
ansible webservers -m command -a "uptime"  # Commande rapide
ansible all -m setup                         # Collecter facts

=== PLAYBOOKS ===
ansible-playbook -i hosts playbook.yml      # Lancer
ansible-playbook ... --check                # Dry-run
ansible-playbook ... -v / -vvv              # Verbosité
ansible-playbook ... --limit web1           # Cibler hôte
ansible-playbook ... --tags deploy          # Lancer par tag
ansible-playbook ... --ask-become-pass     # Demander sudo

=== VAULT ===
ansible-vault create secrets.yml            # Créer chiffré
ansible-vault edit secrets.yml              # Éditer
ansible-vault encrypt fichier.yml           # Chiffrer existant
ansible-vault decrypt fichier.yml           # Déchiffrer
ansible-vault encrypt_string 'mdp' --name x # Valeur inline

=== GALAXY ===
ansible-galaxy collection install community.docker
ansible-galaxy role install geerlingguy.docker

📚 Glossaire des termes

Conteneur
Processus isolé avec son propre système de fichiers. Léger, portable.
Image Docker
Template en lecture seule pour créer des conteneurs. Construite via Dockerfile.
Dockerfile
Fichier texte de recette pour construire une image Docker.
Registry
Dépôt d'images Docker. Docker Hub est le public, tu peux avoir le tien.
Volume
Stockage persistant attaché à un conteneur. Survit à la suppression du conteneur.
Bind Mount
Montage d'un dossier de l'hôte dans le conteneur. Idéal pour le développement.
Network Bridge
Réseau privé isolé pour que des conteneurs communiquent entre eux.
Docker Compose
Outil pour définir et lancer des applications multi-conteneurs via YAML.
Playbook
Fichier YAML Ansible décrivant des tâches d'automatisation à exécuter.
Inventaire
Liste des serveurs gérés par Ansible, organisés en groupes.
Module
Unité d'action Ansible (apt, copy, service...). Des milliers disponibles.
Handler
Tâche Ansible déclenchée uniquement si une autre tâche a effectué un changement.
Facts
Infos collectées automatiquement sur les hôtes (OS, IP, RAM...) avant d'exécuter.
Vault
Système de chiffrement AES-256 d'Ansible pour sécuriser les mots de passe.
Idempotence
Propriété : exécuter N fois = même résultat qu'une fois. Fondamental en Ansible.
Orchestration
Gestion automatisée de nombreux conteneurs (Kubernetes, Docker Swarm).
🎓

Formation terminée !

Tu connais maintenant les bases de Docker et Ansible. Continue à pratiquer : la maîtrise vient avec l'expérience.