Voir le code
%%bash
# Vérifier la version de Docker
docker --version
# Vérifier que Docker fonctionne
docker run --rm hello-world.dockerignore
.dockerignore est-il important ?docker-compose.yml ?Bienvenue dans ce module oĂč tu vas apprendre Ă containeriser tes applications, lancer des services data en quelques secondes, et packager tes pipelines ETL de maniĂšre reproductible et portable â des compĂ©tences indispensables pour un Data Engineer moderne !
| Niveau | Compétence |
|---|---|
| â Requis | Avoir suivi les modules 01_intro_data_engineering et 02_bash_for_data_engineers |
| â Requis | Connaissances de base en Python |
| â Requis | Avoir accĂšs Ă un terminal (Linux, Mac, ou Windows avec WSL) |
Ă la fin de ce module, tu seras capable de :
Docker est un outil qui permet dâexĂ©cuter des applications dans des environnements isolĂ©s, reproductibles et portables, appelĂ©s containers.
Au lieu dâinstaller une application (et toutes ses dĂ©pendances) directement sur ton systĂšme, tu la mets dans une âboĂźteâ (le container) avec tout ce dont elle a besoin.
| Aspect | Machine Virtuelle (VM) | Container Docker |
|---|---|---|
| Contenu | OS complet + kernel + drivers + apps | App + libs + systĂšme minimal |
| Taille | Plusieurs Go | Quelques Mo Ă centaines de Mo |
| Démarrage | Minutes | Secondes/millisecondes |
| Performance | Overhead important | Quasi-natif |
| Isolation | ComplĂšte (hyperviseur) | Au niveau processus |
| Analogie | Explication |
|---|---|
| đ§ł La valise prĂȘte | Un container = une valise dĂ©jĂ remplie. Tu la prends, tu voyages, tu es opĂ©rationnel partout. |
| đ± Le tupperware | Tu prĂ©pares un plat, tu le mets dans une boĂźte hermĂ©tique. Chez toi ou ailleurs : câest le mĂȘme plat. |
| đŠ Le zip complet | Code + librairies + config dans un package. Mais avec la garantie que lâexĂ©cution est identique partout. |
âčïž Le savais-tu ?
Docker a été créé en 2013 par Solomon Hykes chez dotCloud (devenu Docker, Inc.).
Le nom vient des dockers (ouvriers portuaires) qui chargent et dĂ©chargent des containers sur les bateaux â exactement ce que fait Docker avec les applications !
En Data Engineering, tu dois souvent :
| ProblÚme | Conséquence |
|---|---|
| Installation manuelle complexe | Heures perdues en config |
| Conflits de versions (Java, Python, drivers) | âĂa marchait hierâŠâ |
| Environnements diffĂ©rents (local â prod) | Bugs en production uniquement |
| Onboarding difficile | Nouveaux = 2 jours pour installer |
| Avantage | Exemple concret |
|---|---|
| PostgreSQL en 1 commande | docker run postgres:16 |
| Test Kafka + Spark sur laptop | Stack complĂšte en local |
| ETL packagé et portable | Tourne identique partout |
| Onboarding en 10 minutes | docker-compose up et câest parti |
đĄ En rĂ©sumĂ© : Docker est un outil central pour crĂ©er des environnements data reproductibles et industrialisables. Fini le đ âchez moi ça marcheâ !
Avant dâaller plus loin, maĂźtrise ces 6 notions fondamentales :
| Concept | Description | Analogie |
|---|---|---|
| Image | ModÚle figé (blueprint) contenant OS + dépendances + code | Une recette de cuisine |
| Container | Instance en cours dâexĂ©cution dâune image | Un plat prĂ©parĂ© Ă partir de la recette |
| Registry | Magasin dâimages (Docker Hub, ECR, GHCR) | Un catalogue de recettes en ligne |
| Volume | Stockage persistant en dehors du container | Un disque dur externe branché |
| Network | Réseau virtuel entre containers | Un réseau local privé |
| Build context | Fichiers envoyés à Docker lors du build | Le dossier de travail |
Une image contient : - Un systĂšme de base (ex: python:3.11-slim) - Des bibliothĂšques (pandas, pyarrow, pysparkâŠ) - Ton code (scripts, fichiers de config)
On ne modifie pas une image â on en reconstruit une nouvelle Ă partir dâun Dockerfile.
Un container est une instance vivante dâune image : - Tu crĂ©es une image â tu la lances â tu obtiens un container - Tu peux dĂ©marrer, arrĂȘter, supprimer un container sans toucher Ă lâimage - Plusieurs containers peuvent tourner Ă partir de la mĂȘme image
Un registry stocke et partage les images : - Docker Hub (public/privĂ©) â le plus connu - GitHub Container Registry (GHCR) - AWS ECR, GCP Artifact Registry, Azure ACR
Les donnĂ©es ne doivent pas âmourirâ avec le container : - Sans volume : container supprimĂ© = donnĂ©es perdues - Avec volume : donnĂ©es persistantes, partageables
Permet aux containers de communiquer entre eux : - Ex: container etl se connecte à container postgres - Isolation du réseau de la machine hÎte
Quand tu fais docker build -t mon-image . : - Le . = tout ce que Docker envoie au daemon - Dossier de 10 Go = envoi de 10 Go - DâoĂč lâimportance du .dockerignore !
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
â DOCKER HOST â
â (Laptop / Server / Cloud) â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ€
â â
â âââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â DOCKER ENGINE â â
â â â â
â â ââââââââââââ ââââââââââââ ââââââââââââ â â
â â â IMAGE â â IMAGE â â IMAGE â â â
â â â postgres â â python â â spark â â â
â â ââââââŹââââââ ââââââŹââââââ ââââââŹââââââ â â
â â â â â â â
â â ⌠⌠⌠â â
â â ââââââââââââ ââââââââââââ ââââââââââââ â â
â â âCONTAINER â âCONTAINER â âCONTAINER â â â
â â â de-postgresâ â de-etl â â de-spark â â â
â â ââââââŹââââââ ââââââââââââ ââââââââââââ â â
â â â â â
â â ⌠â â
â â ââââââââââââ ââââââââââââââââ â â
â â â VOLUME â â NETWORK â â â
â â â pg_data â â de-network â â â
â â ââââââââââââ ââââââââââââââââ â â
â âââââââââââââââââââââââââââââââââââââââââââââââââââââââ â
â â
âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
| SystĂšme | Comment installer |
|---|---|
| đȘ Windows | Docker Desktop + WSL2 |
| đ macOS | Docker Desktop (Intel ou Apple Silicon) |
| đ§ Linux | Docker Engine (apt/yum) |
1. Activer WSL2 :
2. TĂ©lĂ©charger Docker Desktop : - đ https://www.docker.com/products/docker-desktop/
3. Installer et redémarrer
4. Tester :
1. TĂ©lĂ©charger Docker Desktop : - đ https://www.docker.com/products/docker-desktop/ - Choisir la version Intel ou Apple Silicon (M1/M2/M3)
2. Glisser lâapp dans Applications
3. Lancer Docker Desktop (icĂŽne đł dans la barre)
4. Tester :
# 1. Mettre à jour et installer les prérequis
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg lsb-release
# 2. Ajouter la clé GPG officielle
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# 3. 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
# 4. Installer Docker
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
# 5. Tester
sudo docker run --rm hello-world
# 6. (Optionnel) Utiliser Docker sans sudo
sudo usermod -aG docker $USER
# Puis déconnexion/reconnexionVoici ton cheat sheet de base :
| Commande | Description |
|---|---|
docker ps -a |
Voir tous les containers |
docker logs -f |
Suivre les logs en live |
docker exec -it <container> bash |
Entrer dans un container |
docker system prune |
Nettoyer les ressources inutilisées |
Docker est extrĂȘmement pratique pour tester rapidement des services utilisĂ©s en Data Engineering.
Connexion : - Host: localhost - Port: 5432 - User: de_user - Password: de_pass - Database: de_db
Tu peux ensuite te connecter avec DBeaver, psql, Python (psycopg2), etc.
| Service | Commande |
|---|---|
| Redis | docker run -d --name demo-redis -p 6379:6379 redis:latest |
| MongoDB | docker run -d --name demo-mongo -p 27017:27017 mongo:latest |
| Kafka | docker run -d --name demo-kafka -p 9092:9092 bitnami/kafka:latest |
| Spark | docker run -it --name demo-spark bitnami/spark:latest pyspark |
| Airflow | docker pull apache/airflow:latest |
| Jupyter | docker run -p 8888:8888 jupyter/scipy-notebook |
đĄ Astuce : Pour Kafka et Airflow, prĂ©fĂšre
docker-composecar ils nĂ©cessitent plusieurs services (Zookeeper, webserver, schedulerâŠ), on le verra un peu plus en bas.
%%bash
# Lancer PostgreSQL (si Docker est installé)
docker run -d \
--name demo-postgres \
-e POSTGRES_USER=de_user \
-e POSTGRES_PASSWORD=de_pass \
-e POSTGRES_DB=de_db \
-p 5432:5432 \
postgres:16
echo "PostgreSQL lancé sur localhost:5432"
# Vérifier qu'il tourne
docker ps --filter name=demo-postgresLe Dockerfile est un fichier texte qui décrit comment construire une image.
| Instruction | RĂŽle | Exemple |
|---|---|---|
FROM |
Image de base | FROM python:3.11-slim |
WORKDIR |
Répertoire de travail | WORKDIR /app |
COPY |
Copier des fichiers | COPY etl.py . |
RUN |
Exécuter une commande (build) | RUN pip install pandas |
CMD |
Commande par défaut (run) | CMD ["python", "etl.py"] |
ENTRYPOINT |
Point dâentrĂ©e fixe | ENTRYPOINT ["python"] |
ENV |
Variable dâenvironnement | ENV PYTHONUNBUFFERED=1 |
EXPOSE |
Port exposé (documentation) | EXPOSE 8000 |
etl_project/
âââ Dockerfile
âââ .dockerignore
âââ requirements.txt
âââ src/
â âââ etl.py
â âââ utils.py
âââ data/ # â ïž Ne pas inclure dans l'image !
âââ input.csv
đĄ Important : Le Dockerfile doit ĂȘtre Ă la racine du service que tu veux packager.
# 1. Image de base légÚre
FROM python:3.11-slim
# 2. Variables d'environnement
ENV PYTHONUNBUFFERED=1
ENV PYTHONDONTWRITEBYTECODE=1
# 3. Répertoire de travail
WORKDIR /app
# 4. Copier et installer les dépendances (cache Docker)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 5. Copier le code
COPY src/ ./src/
# 6. Commande par défaut
CMD ["python", "src/etl.py"].dockerignoreLe .dockerignore empĂȘche dâenvoyer des fichiers inutiles dans le build context.
.dockerignore.dockerignore (Data Engineer)# Données
data/
*.csv
*.parquet
*.json
# Python
__pycache__/
*.pyc
*.pyo
venv/
.venv/
*.egg-info/
# Secrets
.env
*.key
*.pem
secrets/
# Notebooks
*.ipynb
.ipynb_checkpoints/
# Git
.git/
.gitignore
# IDE
.idea/
.vscode/
*.swp
# Logs
logs/
*.log
# OS
.DS_Store
Thumbs.db
# Docker
Dockerfile
docker-compose*.yml
đĄ RĂšgle dâor : le
.dockerignoreest aussi important que le Dockerfile !
Les multi-stage builds permettent de créer des images plus légÚres en séparant :
| Sans multi-stage | Avec multi-stage |
|---|---|
| Image de 1.5 Go | Image de 200 Mo |
| Outils de build inclus | Seulement le runtime |
| Surface dâattaque large | SĂ©curitĂ© renforcĂ©e |
# ============== STAGE 1 : BUILD ==============
FROM python:3.11-slim AS builder
WORKDIR /app
# Installer les dépendances dans un dossier isolé
COPY requirements.txt .
RUN pip install --prefix=/install --no-cache-dir -r requirements.txt
# ============== STAGE 2 : RUNTIME ==============
FROM python:3.11-slim AS runtime
WORKDIR /app
# Copier seulement les dépendances installées
COPY --from=builder /install /usr/local
# Copier le code
COPY src/ ./src/
# Variables d'environnement
ENV PYTHONUNBUFFERED=1
CMD ["python", "src/etl.py"]RĂ©sultat : image finale lĂ©gĂšre et sĂ©curisĂ©e ! đ
Les volumes permettent de stocker des données en dehors des containers.
Types de volumes :
| Type | Syntaxe | Usage |
|---|---|---|
| Bind mount | -v /host/path:/container/path |
Données locales (dev) |
| Volume nommé | -v myvolume:/container/path |
Données persistantes (prod) |
Exemple : monter un dossier local
$(pwd)/data â dossier sur ta machine/app/data â dossier dans le container./dataPar dĂ©faut, Docker crĂ©e un rĂ©seau bridge. Tu peux crĂ©er un rĂ©seau dĂ©diĂ© :
Avantage : dans le code Python, tu te connectes Ă de-postgres (nom du container) au lieu de localhost !
Quand tu as plusieurs services (Postgres + ETL + APIâŠ), tu ne veux pas tout lancer Ă la main.
docker-compose.yml permet de décrire une stack complÚte et de la lancer avec une seule commande.
de-pipeline/
âââ docker-compose.yml # Ă la racine !
âââ etl/
â âââ Dockerfile
â âââ requirements.txt
â âââ etl.py
âââ data/
âââ input.csv
version: "3.9"
services:
postgres:
image: postgres:16
container_name: de-postgres
environment:
POSTGRES_USER: de_user
POSTGRES_PASSWORD: de_pass
POSTGRES_DB: de_db
ports:
- "5432:5432"
volumes:
- pg_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U de_user -d de_db"]
interval: 5s
timeout: 5s
retries: 5
etl:
build: ./etl
container_name: de-etl
depends_on:
postgres:
condition: service_healthy
environment:
DB_HOST: postgres
DB_USER: de_user
DB_PASSWORD: de_pass
DB_NAME: de_db
volumes:
- ./data:/app/data
volumes:
pg_data:En Data Engineering, tu devras souvent débugger un job qui tourne dans un container.
Cas dâusage : - Inspecter les fichiers (ls, cat) - Tester une connexion DB (psql, ping) - VĂ©rifier les variables dâenvironnement (env) - Lancer un script manuellement (python etl.py)
| ProblĂšme | Solution |
|---|---|
| ETL qui plante sans message | docker logs de-etl |
| Connexion DB refusée | docker exec -it de-etl bash puis ping postgres |
| Spark ne voit pas Kafka | Vérifier les networks Docker |
| Fichier introuvable | docker exec -it de-etl ls /app/data |
| Variable dâenv manquante | docker exec -it de-etl env |
| Erreur | Conséquence | Solution |
|---|---|---|
Pas de .dockerignore |
Images de plusieurs Go | Créer un .dockerignore complet |
Tout en latest |
Comportement non reproductible | Tags versionnés (image:1.0.0) |
| Dockerfile mal placé | Build context gigantesque | Dockerfile à la racine du service |
| Secrets dans lâimage | Fuite de credentials | Variables dâenv ou secrets manager |
| Pas de nettoyage | Disque saturé | docker system prune réguliÚrement |
| DonnĂ©es dans lâimage | Image Ă©norme, non portable | Utiliser des volumes |
| Versions non fixées | Builds cassés aprÚs mise à jour | Fixer les versions dans requirements.txt |
| Pratique | Pourquoi |
|---|---|
| Images slim | python:3.11-slim = plus léger et rapide |
| Multi-stage builds | Images finales légÚres |
| Tags versionnés | etl:1.0.0, etl:prod, etl:staging |
.dockerignore |
Builds rapides et sécurisés |
| Healthchecks | Savoir si un service est prĂȘt |
| Volumes pour les données | Persistance et portabilité |
| Nettoyage régulier | docker system prune |
Réponds aux questions suivantes pour vérifier tes acquis.
â RĂ©ponse : b â Une image est un modĂšle figĂ©, un container est son exĂ©cution vivante.
.dockerignore est-il important ?â RĂ©ponse : b â Il Ă©vite dâenvoyer des fichiers inutiles (donnĂ©es, secrets) dans le build context.
docker run -it container bashdocker exec -it container bashdocker enter containerdocker ssh containerâ
RĂ©ponse : b â docker exec -it <container> bash ouvre un shell interactif.
â RĂ©ponse : b â Multi-stage = image finale lĂ©gĂšre avec seulement le runtime nĂ©cessaire.
docker-compose.yml ?/etc/docker/â
RĂ©ponse : b â Le docker-compose.yml est Ă la racine du projet, avec les services dans des sous-dossiers.
docker logs containerdocker logs -f containerdocker watch containerdocker tail containerâ
RĂ©ponse : b â Lâoption -f (follow) suit les logs en temps rĂ©el.
Créer un pipeline ETL Dockerisé qui lit un CSV, transforme les données, et les charge dans PostgreSQL.
Tu dois packager un job ETL Python avec Docker et le faire communiquer avec une base PostgreSQL, le tout orchestré par docker-compose.
de-mini-projet/
âââ docker-compose.yml
âââ etl/
â âââ Dockerfile
â âââ .dockerignore
â âââ requirements.txt
â âââ etl.py
âââ data/
âââ sales.csv
LâETL doit :
data/sales.csvtotal = quantity * priceUtiliser un healthcheck pour attendre que Postgres soit prĂȘt
Les donnĂ©es doivent ĂȘtre montĂ©es via un volume
1. data/sales.csv
date,product,quantity,price
2024-01-01,Laptop,5,999.99
2024-01-02,Mouse,20,29.99
2024-01-03,Keyboard,15,79.99
2024-01-04,Monitor,8,299.99
2024-01-05,Laptop,3,999.99
2. etl/requirements.txt
pandas==2.1.4
psycopg2-binary==2.9.9
sqlalchemy==2.0.25
3. etl/.dockerignore
__pycache__/
*.pyc
.env
*.log
4. etl/Dockerfile
5. etl/etl.py
import os
import pandas as pd
from sqlalchemy import create_engine
def main():
# Configuration depuis variables d'environnement
db_host = os.environ.get('DB_HOST', 'localhost')
db_user = os.environ.get('DB_USER', 'de_user')
db_pass = os.environ.get('DB_PASSWORD', 'de_pass')
db_name = os.environ.get('DB_NAME', 'de_db')
print("đ DĂ©marrage de l'ETL...")
# Extract
print("đ„ Lecture du fichier CSV...")
df = pd.read_csv('/app/data/sales.csv')
print(f" {len(df)} lignes lues")
# Transform
print("đ Transformation des donnĂ©es...")
df['total'] = df['quantity'] * df['price']
df['loaded_at'] = pd.Timestamp.now()
# Load
print("đ€ Chargement dans PostgreSQL...")
engine = create_engine(f'postgresql://{db_user}:{db_pass}@{db_host}/{db_name}')
df.to_sql('sales', engine, if_exists='replace', index=False)
print("â
ETL terminé avec succÚs !")
print(df.head())
if __name__ == "__main__":
main()6. docker-compose.yml
version: "3.9"
services:
postgres:
image: postgres:16
container_name: de-postgres
environment:
POSTGRES_USER: de_user
POSTGRES_PASSWORD: de_pass
POSTGRES_DB: de_db
ports:
- "5432:5432"
volumes:
- pg_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U de_user -d de_db"]
interval: 5s
timeout: 5s
retries: 5
etl:
build: ./etl
container_name: de-etl
depends_on:
postgres:
condition: service_healthy
environment:
DB_HOST: postgres
DB_USER: de_user
DB_PASSWORD: de_pass
DB_NAME: de_db
volumes:
- ./data:/app/data
volumes:
pg_data:7. Lancer le projet :
8. Vérifier les données dans Postgres :
Maintenant que tu maĂźtrises Docker, passons Ă lâorchestration de containers Ă grande Ă©chelle !
đ Module suivant : 15_kubernetes_fundamentals â Orchestrer des containers avec Kubernetes
Tu vas apprendre : - Pods, Deployments, Services - ConfigMaps, Secrets - Spark et Airflow sur Kubernetes
đ FĂ©licitations ! Tu as terminĂ© le module Docker pour Data Engineers.