Dockeriser une API Flask de zéro sur Ubuntu : le guide complet
Il y a un problème que tout développeur africain a vécu au moins une fois.
Tu construis une app. Elle tourne parfaitement sur ta machine. Tu l’envoies en production — ou à ton collègue, ou au client. Elle plante.
“Mais ça marchait chez moi…”
Docker est la solution définitive à ce problème. Dans ce guide, je te montre comment dockeriser une API Flask réelle, de bout en bout, sur Ubuntu — avec les bonnes pratiques de production dès le départ.
Ce qu’on va construire
À la fin de ce guide, tu auras :
- Un projet Flask cloné depuis GitHub et analysé
- Un Dockerfile optimisé avec gestion intelligente du cache
- Une app servie par Gunicorn (le vrai serveur de prod, pas
flask run) - Une configuration sécurisée par variables d’environnement
- Une image versionnée et publiée sur Docker Hub
Prérequis
- Ubuntu 22.04 ou 24.04
- Docker installé (guide officiel)
- Git installé
- Connaissances de base en Python et ligne de commande
Étape 1 — Installer Docker sur Ubuntu
Sur Ubuntu, Docker s’installe nativement — pas besoin de virtualisation comme sur Windows.
# Supprime les anciennes versions si présentes
for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do
sudo apt-get remove $pkg
done
# Installe Docker via le script officiel
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
# Autorise ton utilisateur à utiliser Docker sans sudo
sudo usermod -aG docker $USER
newgrp docker
# Vérifie l'installation
docker run hello-world
Si tu vois Hello from Docker! — tu es prêt.
Étape 2 — Cloner et analyser le projet Flask
On part d’un projet existant, comme tu le ferais dans une vraie mission.
git clone https://github.com/gothinkster/flask-realworld-example-app.git
cd flask-realworld-example-app
Avant de toucher quoi que ce soit, lis ces trois fichiers :
cat requirements.txt # Les dépendances Python
cat autoapp.py # Le point d'entrée de l'app
cat README.md # La documentation existante
Ce réflexe — lire avant d’agir — est la marque d’un développeur qui pense avant de coder. C’est ce que cherche un tech lead.
La structure du projet :
flask-realworld-example-app/
├── autoapp.py ← Point d'entrée Flask
├── requirements.txt ← Dépendances Python
└── conduit/ ← Code de l'API
Étape 3 — Écrire le Dockerfile
C’est l’étape centrale. Chaque instruction a une raison précise.
# Image de base : Python 3.10 allégée (150 Mo au lieu de 900 Mo)
FROM python:3.10-slim
# Dossier de travail dans le container
WORKDIR /app
# ÉTAPE CLÉE : copier requirements.txt EN PREMIER
COPY requirements.txt .
# Installer les dépendances sans cache pip
RUN pip install --no-cache-dir -r requirements.txt
# Installer Gunicorn — le serveur de production
RUN pip install gunicorn
# Copier le code APRÈS les dépendances
COPY . .
# Documenter le port utilisé
EXPOSE 5000
# Démarrer avec Gunicorn
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "autoapp:app"]
Pourquoi cet ordre précis ?
Docker construit l’image couche par couche. Chaque instruction crée une couche mise en cache.
Si tu copies tout le code d’abord (COPY . .), puis tu fais pip install — le moindre changement dans ton code invalide le cache et force une réinstallation complète de toutes les dépendances.
En copiant requirements.txt seul en premier, le pip install n’est relancé que si les dépendances changent. Si tu modifies juste ton code — le rebuild passe directement au COPY . ..
30 secondes économisées à chaque rebuild. Sur 50 rebuilds par semaine, ça compte.
Pourquoi Gunicorn ?
Le serveur intégré de Flask (flask run) est :
- Mono-thread (une requête à la fois)
- Non sécurisé pour la production
- Prévu uniquement pour le développement
Gunicorn gère plusieurs workers en parallèle et est conçu pour la production.
Pourquoi 0.0.0.0 ?
127.0.0.1 = accessible uniquement de l’intérieur du container → invisible depuis ton navigateur.
0.0.0.0 = accessible depuis l’extérieur → le port mapping fonctionne.
Étape 4 — Créer le .dockerignore
Sans ce fichier, Docker envoie tout ton dossier au moteur de build — y compris les fichiers inutiles ou dangereux.
# .dockerignore
venv/
.venv/
__pycache__/
*.pyc
.env
.git/
*.md
⚠️
.envdans ce fichier est critique. Sans ça, tes clés secrètes pourraient se retrouver dans l’image Docker publiée sur Docker Hub. Publiquement accessibles.
Étape 5 — Builder l’image
docker build -t mon-api-flask:v1 .
Observe les logs. Chaque step correspond à une instruction du Dockerfile.
Maintenant fais un second build sans rien changer :
docker build -t mon-api-flask:v1 .
Tu verras CACHED sur les steps pip install. Le cache fonctionne.
Vérifie l’image créée :
docker images
# REPOSITORY TAG SIZE
# mon-api-flask v1 ~180MB
Étape 6 — Lancer le container et tester
# Lance le container
docker run -d -p 5000:5000 --name api-flask mon-api-flask:v1
# Vérifie qu'il tourne
docker ps
# Lis les logs Gunicorn
docker logs -f api-flask
Ouvre http://localhost:5000 dans ton navigateur. L’API répond.
Décryptage des flags docker run :
| Flag | Signification |
|---|---|
-d |
Mode détaché — tourne en arrière-plan |
-p 5000:5000 |
Port mapping hôte:container |
--name api-flask |
Nom lisible au lieu d’un hash |
Étape 7 — Sécuriser avec les variables d’environnement
# Crée le fichier de configuration
nano .env
FLASK_ENV=production
SECRET_KEY=change-cette-valeur-en-production
PORT=5000
Relance le container avec ces variables injectées :
docker stop api-flask && docker rm api-flask
docker run -d -p 5000:5000 --name api-flask --env-file .env mon-api-flask:v1
# Vérifie que les variables sont bien reçues
docker exec api-flask env
Le principe : l’image Docker ne contient jamais les valeurs sensibles. Elle les reçoit au moment du lancement. La même image peut tourner en dev, staging et production avec des configurations différentes.
Étape 8 — Publier sur Docker Hub
# Connexion
docker login
# Tag avec ton pseudo Docker Hub
docker tag mon-api-flask:v1 tonpseudo/mon-api-flask:v1
# Push
docker push tonpseudo/mon-api-flask:v1
Ton image est maintenant accessible depuis n’importe quel serveur dans le monde :
# Sur n'importe quelle machine avec Docker
docker pull tonpseudo/mon-api-flask:v1
docker run -d -p 5000:5000 tonpseudo/mon-api-flask:v1
C’est ça, la promesse de Docker : construis une fois, fais tourner partout.
Ce que ce projet t’a appris
| Concept | Ce que tu maîtrises maintenant |
|---|---|
| Layers Docker | L’ordre des instructions = stratégie de cache |
| Port mapping |
-p hôte:container — sans ça, l’app est invisible |
.dockerignore |
Protège les secrets, allège le build |
| Variables d’env | Séparation config/code — principe 12-factor |
| Gunicorn | Serveur WSGI de production pour Python |
| Docker Hub | Registry public — le “GitHub” des images |
Pour aller plus loin
- Docker Compose + PostgreSQL — Ajouter une base de données persistante connectée à Flask
-
GitHub Actions CI/CD — Automatiser build + push à chaque
git push - Déploiement VPS — Nginx reverse proxy + HTTPS via Let’s Encrypt
Conclusion
Tu n’as plus besoin de dire “ça marchait chez moi”.
Ton app Flask est dans une boîte hermétique. Elle tourne sur ton Ubuntu, sur le serveur du client, sur la machine de ton collègue — de manière identique, sans rien réinstaller.
C’est exactement ce qu’un client freelance ou un recruteur veut voir : pas juste du code qui tourne en local, mais un artefact déployable et professionnel.
Le projet est sur GitHub et l’image sur Docker Hub — liens en fin d’article.
Roméo DOSSOU — Cloud & DevSecOps Engineer | Ouidah, Bénin
Je publie des guides pratiques Docker, Kubernetes et Cloud pour les ingénieurs francophones africains.