5.3Docker pour Python
L'essentiel en 30 secondes
- Fini le « ça marche sur ma machine » : le conteneur embarque l'app avec son environnement et tourne identiquement partout.
- Dépendances avant code : base slim, requirements copiés et installés d'abord — le cache survit aux modifications.
- Dev vs prod : bind mount + reload en dev, code copié + workers en prod — même image de base.
Mini-cas filé — Nabil conteneurise à Alger
Le pipeline async de Nabil tourne parfaitement à Alger — mais plante chez sa collègue (version de Python différente, dépendances manquantes, port injoignable). Il écrit un Dockerfile : base slim, requirements installés avant le code, utilisateur non-root, lancement sur toutes les interfaces. Puis un Compose avec la base de données. Suite des cas 5.1-5.2 — Nabil rend son analyse portable.
Suite des cas 5.1-5.2 — Nabil passe de « chez moi ça marche » à « partout pareil ».
1. Le Dockerfile Python qui marche
Docker empaquette l'app Python avec son environnement complet (version de Python, dépendances, système) dans un conteneur qui s'exécute à l'identique partout. La recette (Dockerfile) : base python:3.12-slim, COPY requirements.txt puis pip install avant le code (le cache de build survit aux modifications), USER non-root, CMD qui lance. Le .dockerignore exclut .venv, __pycache__ et .git : le contexte maigrit, le build accélère. Nabil ne débat plus des versions : l'environnement voyage avec le code.
Réflexe : tout ce qui vit sur votre poste et manque dans l'image est un futur plantage ailleurs — l'image doit tout contenir, dépendances comprises.
2. Dev vs prod : deux visages
Même image de base, deux lancements. En dev : bind mount du code + --reload (FastAPI/Flask) — on modifie, ça recharge sans reconstruire. En prod : code copié dans l'image, serveur gunicorn/uvicorn en multi-workers, config par variables -e, écoute sur 0.0.0.0 (jamais localhost, injoignable en conteneur). Nabil développe en bind et livre en copié : deux visages, une seule recette.
À éviter : confondre les deux — du reload en prod, ou du code copié figé en dev qui force un rebuild à chaque virgule.
3. Compose pour l'appli complète
Une appli réelle, c'est plusieurs conteneurs : api (build du Dockerfile) + bdd (base + volume persistant) sur un même réseau, DATABASE_URL en variable, depends_on + retry au démarrage. Compose décrit tout ça et monte le stack local identique à la CI d'une commande. Nabil ajoute la base au Compose : sa collègue démarre en minutes, avec les mêmes versions.
Le niveau 3 du guide Docker détaille chaque ligne : ici, on retient le geste — une commande, tout le stack, partout pareil.
🔎 Exemple concret — L'API de Nabil en conteneur
Recette générique : slim, cache, non-root, écoute ouverte.
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
RUN useradd -m app && chown -R app:app /app
USER app
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Lecture : le requirements caché avant le code changeant — le cache survit aux virgules.
Leçon : --host 0.0.0.0 obligatoire en conteneur, jamais localhost.
Vocabulaire de la section
- Docker
- Outil qui empaquette l'app et son environnement dans un conteneur portable.
Exemple simple : L'analyse de Nabil tourne pareil à Alger et chez sa collègue.
Ce que ce n'est pas : un venv recréé à la main sur chaque poste.
Réflexe : mon app dépend-elle encore de mon poste ?
- Image
- Modèle figé de l'app + dépendances, construit depuis le Dockerfile.
Exemple simple : Nabil construit une image versionnée de chaque livraison.
Ce que ce n'est pas : le conteneur en cours d'exécution.
Réflexe : puis-je reconstruire cette image à l'identique ?
- Dockerfile
- Recette de construction : base slim, dépendances, code, lancement.
Exemple simple : La recette lisible de Nabil, requirements avant code.
Ce que ce n'est pas : une install manuelle de Python sur un serveur.
Réflexe : les dépendances sont-elles installées avant le code ?
- .dockerignore
- Exclut l'inutile du contexte (.venv, caches, .git) pour maigrir le build.
Exemple simple : Nabil exclut .venv et __pycache__ : build plus rapide.
Ce que ce n'est pas : copier .venv dans l'image.
Réflexe : qu'est-ce qui alourdit mon contexte ?
- Compose
- Décrit plusieurs conteneurs (api + bdd) lancés ensemble.
Exemple simple : Nabil monte api et base d'une seule commande.
Ce que ce n'est pas : un seul conteneur isolé sans base.
Réflexe : un nouvel arrivant démarre-t-il en une commande ?
En pratique — Conteneuriser une application Python
- Installez Docker Desktop. Préparez une petite app Python (ex. un script ou une API FastAPI) avec son requirements.txt.
- Écrivez un Dockerfile : image de base « FROM python:3.12-slim », copie du code, « RUN pip install -r requirements.txt », commande de lancement (CMD).
- Construisez l'image : « docker build -t mon-app . », puis lancez un conteneur : « docker run mon-app » (avec -p pour exposer un port si c'est une API).
- Modifiez le code, reconstruisez, relancez : mesurez la reproductibilité — le conteneur tourne à l'identique partout.
Script prêt à dire — proposer Docker à l'équipe
« Notre analyse marche sur mon poste à Alger mais pas ailleurs : c'est un problème d'environnement, pas de code — version de Python, dépendances. Je propose un Dockerfile slim avec requirements installés avant le code, USER non-root, plus un Compose avec la base. Chacun lancera la même image, et les secrets resteront hors de l'image, en variables d'environnement. »
À dire en réunion pour faire adopter la conteneurisation sans viser l'expertise DevOps.
Modèle copier-coller — Dockerfile Python + Compose génériques
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
RUN useradd -m app && chown -R app:app /app
USER app
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
# --- docker-compose.yml (stack generique) ---
# services:
# api:
# build: .
# ports: ["8000:8000"]
# environment:
# - DATABASE_URL=postgresql://db:5432/app
# db:
# image: postgres:16
# volumes: ["pgdata:/var/lib/postgresql/data"]
Solo / petit budget
Nabil seul : un Dockerfile slim sans Compose suffit — l'image fige déjà Python et les dépendances.
TPE / équipe réduite
Compose api + bdd : chaque collègue démarre le stack complet sans installer Python ni la base.
PME à Alger
Nabil partage l'image à Alger : tout le monde teste la même version, fin des écarts de poste.
Équipe qui démarre
Binôme : l'un écrit le Dockerfile, l'autre vérifie USER, .dockerignore et 0.0.0.0 avant adoption.
✓ Bonnes pratiques
- slim + cache : requirements d'abord, code ensuite.
- USER non-root systématique ; .dockerignore contre .venv et caches.
- 0.0.0.0 en conteneur, jamais localhost.
✗ Pièges fréquents
- Copier .venv dans l'image (lourde, non portable).
- Écouter sur localhost : le service reste injoignable.
- Confondre dev (bind + reload) et prod (copié + workers).
Points clés à retenir
- Docker empaquette l'app + son environnement : fini le « ça marche sur ma machine ».
- Image = modèle figé ; conteneur = instance en exécution.
- Le Dockerfile décrit la recette de construction de l'image.
- build (construire) puis run (lancer) : le cycle de base de Docker.
Défi 48h — appliquez demain
Écrivez le Dockerfile de votre app (modèle ci-dessus) et lancez-la en conteneur : répond-elle pareil que sur votre poste ?
- Je peux expliquer image vs conteneur en une phrase.
- Mon Dockerfile construit une image qui tourne.
- Je sais pourquoi les secrets n'y figurent pas.
Questions fréquentes
Docker remplace-t-il les environnements virtuels (venv) ?
Ils opèrent à des niveaux différents. Le venv isole les dépendances Python d'un projet sur votre machine. Docker isole l'application entière (Python, système, dépendances) dans un conteneur portable. En pratique, on utilise souvent un venv en développement et Docker pour livrer/déployer — complémentaires, pas concurrents.
Docker est-il nécessaire pour un débutant ?
Pas pour apprendre le langage. Mais dès qu'on déploie une application réelle, qu'on travaille en équipe ou qu'on vise le cloud, Docker devient un standard quasi incontournable. C'est une compétence très valorisée : l'aborder au niveau pro est le bon moment.
Quel problème Docker résout-il principalement ?