MinIO
Un serveur de stockage objet compatible S3, auto-hébergeable, écrit en Go. Tu lances un conteneur Docker et tu obtiens un « Amazon S3 » sur ta propre machine : datasets, modèles, artefacts, sauvegardes.
À quoi ça sert
MinIO fait la même chose qu'Amazon S3 — stocker des fichiers (« objets ») dans des « buckets » accessibles par HTTP — mais chez toi. Même API, mêmes commandes, mêmes SDK. Tu peux développer en local contre MinIO puis pointer la même appli sur S3 en prod sans rien changer.
- Backend de stockage pour MLflow — datasets, artefacts, poids de modèles versionnés.
- Stockage de datasets — images, vidéos, audios trop gros pour Git ou une base SQL.
- Backups — dumps de base, snapshots, archives.
- Partage entre services — une API dépose un fichier, un worker le récupère plus tard.
- CDN privé — servir des assets web (images, vidéos).
Le stockage fichier (NFS, disque local) organise les données en arborescence avec des permissions Unix. Le stockage bloc (SSD, EBS) expose des volumes bruts qu'on formate. Le stockage objet — la spécialité de MinIO et S3 — voit chaque fichier comme un « objet » identifié par une clé, accédé en HTTP, sans hiérarchie réelle de dossiers. C'est le modèle qui scale le mieux pour des milliards de fichiers et qui est devenu le standard du cloud.
Le concept S3 en 3 termes
- Bucket — un « dossier racine » qui contient des objets.
Tu en crées un par usage (
datasets,mlflow,backups). Son nom est unique sur le serveur. - Objet — un fichier dans un bucket, identifié par une
clé (qui peut contenir des
/simulant des dossiers, mais ce n'est qu'un préfixe textuel). - Access Key + Secret Key — l'identifiant et le mot de passe utilisés par les SDK pour s'authentifier (équivalent login/password pour HTTP basic, mais utilisé dans tous les SDK S3).
Amazon a publié l'API de S3 sans la breveter, et tout l'écosystème
cloud s'est aligné dessus. Du coup MinIO, Backblaze B2, Cloudflare R2,
Wasabi, OVH Object Storage parlent la même langue.
Tu écris ton code avec le SDK boto3 (Amazon) ou
minio, et tu changes juste l'URL pour basculer d'un
fournisseur à l'autre.
Un exemple d'usage
Démarrer MinIO en local avec Docker et y déposer un fichier en 3 minutes :
# 1. Lancer le serveur MinIO
docker run -d --name minio \
-p 9000:9000 -p 9001:9001 \
-e MINIO_ROOT_USER=admin \
-e MINIO_ROOT_PASSWORD=adminadmin \
-v minio-data:/data \
quay.io/minio/minio server /data --console-address ":9001"
Tu accèdes ensuite à la console web sur
http://localhost:9001 (login admin /
adminadmin), tu crées un bucket à la souris, et tu y déposes
un fichier. L'API S3 elle-même tourne sur le port 9000.
Depuis Python, on uploade un fichier en quelques lignes :
from minio import Minio
client = Minio(
"localhost:9000",
access_key="admin",
secret_key="adminadmin",
secure=False, # pas de TLS en local
)
# Créer un bucket s'il n'existe pas
if not client.bucket_exists("datasets"):
client.make_bucket("datasets")
# Uploader un fichier
client.fput_object("datasets", "images/chat.jpg", "./chat.jpg")
How-to : installer et utiliser MinIO
-
Lancer MinIO avec Docker Compose
En pratique on utilise Docker Compose pour faire tourner MinIO durablement, avec un volume persistant.
yaml (docker-compose.yml)services: minio: image: quay.io/minio/minio:latest command: server /data --console-address ":9001" ports: - "9000:9000" # API S3 - "9001:9001" # Console web environment: MINIO_ROOT_USER: admin MINIO_ROOT_PASSWORD: adminadmin volumes: - minio-data:/data restart: unless-stopped volumes: minio-data:bashdocker compose up -dChoisir un mot de passe sérieux dès le départMinIO refuse de démarrer si le mot de passe fait moins de 8 caractères. En prod, mets-les dans un
.env(jamais dans le YAML committé). Le compteMINIO_ROOT_USERest root, équivalent à un administrateur S3. -
Créer un bucket via la console web
Ouvre
http://localhost:9001, connecte-toi, puis Buckets → Create Bucket. Donne un nom (en minuscules, sans espaces :mlflow-artifacts,datasets). C'est le moyen le plus simple pour démarrer. -
Créer des access keys dédiées
Plutôt que de partager le compte root, on crée des paires access key / secret key par application : Access Keys → Create Access Key. Tu obtiens deux chaînes à passer à ton SDK. On peut limiter leurs permissions par policy (lecture seule, accès à un bucket précis…).
-
Installer un client Python
Deux options : la lib officielle
minio(légère, axée MinIO mais marche aussi sur S3), ouboto3(AWS, plus répandue, marche aussi sur MinIO). On reste dans la logique UV.bashuv add minio # client officiel MinIO # ou uv add boto3 # SDK AWS, fonctionne aussi sur MinIO -
Uploader, lister, télécharger des objets
python (lib minio)from minio import Minio client = Minio( "localhost:9000", access_key="admin", secret_key="adminadmin", secure=False, ) # Uploader un fichier local client.fput_object("datasets", "img/01.jpg", "./01.jpg") # Lister les objets d'un bucket for obj in client.list_objects("datasets", recursive=True): print(obj.object_name, obj.size) # Télécharger client.fget_object("datasets", "img/01.jpg", "./local.jpg") # Supprimer client.remove_object("datasets", "img/01.jpg")Avec
boto3, la même chose mais syntaxe AWS :python (boto3)import boto3 s3 = boto3.client( "s3", endpoint_url="http://localhost:9000", aws_access_key_id="admin", aws_secret_access_key="adminadmin", ) s3.upload_file("./01.jpg", "datasets", "img/01.jpg") s3.download_file("datasets", "img/01.jpg", "./local.jpg") -
Générer une URL temporaire (presigned URL)
Un cas très courant : tu veux qu'un utilisateur puisse télécharger un fichier privé pendant 1 heure, sans lui donner les credentials. MinIO sait générer une URL signée qui expire :
pythonfrom datetime import timedelta url = client.presigned_get_object( "datasets", "img/01.jpg", expires=timedelta(hours=1), ) print(url) # http://localhost:9000/datasets/img/01.jpg?X-Amz-...On utilise la même méthode
presigned_put_object()pour autoriser un upload — l'utilisateur peut alors envoyer son fichier directement à MinIO sans transiter par ton API. -
Le client en ligne de commande (mc)
MinIO fournit un CLI
mctrès pratique pour les opérations d'admin (un peu commeaws s3pour AWS). On le lance dans un conteneur :bash# Enregistrer le serveur sous l'alias "local" docker run --rm --network host \ quay.io/minio/mc alias set local http://localhost:9000 admin adminadmin # Lister les buckets docker run --rm --network host quay.io/minio/mc ls local # Copier un dossier entier docker run --rm -v $(pwd):/data --network host \ quay.io/minio/mc cp --recursive /data/photos local/datasets/
Aide-mémoire
client.make_bucket("bucket")
client.bucket_exists("bucket")
client.list_buckets()
client.fput_object("b", "key", "./file")
client.fget_object("b", "key", "./out")
client.list_objects("b", recursive=True)
client.remove_object("b", "key")
client.presigned_get_object("b", "key", expires=timedelta(hours=1))
mc alias set local http://localhost:9000 admin pass
mc ls local # liste buckets
mc ls local/bucket --recursive
mc cp ./file local/bucket/key
mc cp --recursive ./folder local/bucket/
mc mirror ./local local/bucket # sync (rsync-like)
mc rm local/bucket/key
mc admin info local # état du serveur
MINIO_ENDPOINT=http://minio:9000
MINIO_ACCESS_KEY=...
MINIO_SECRET_KEY=...
MINIO_BUCKET=mlflow-artifacts
MinIO et le reste de l'écosystème
-
MLflow — le combo le plus
classique en MLOps. MLflow stocke ses artefacts (modèles,
métriques, plots) dans MinIO en pointant
MLFLOW_S3_ENDPOINT_URLvers ton instance. -
Docker — MinIO se déploie
toujours en conteneur, c'est la façon de l'installer en
pratique. Image officielle
quay.io/minio/minio. -
FastAPI — pattern classique :
ton API reçoit un upload, l'envoie à MinIO via
boto3, stocke seulement la clé en base. Pour les gros fichiers, on donne plutôt une presigned URL au client pour qu'il uploade directement. - Kubernetes — MinIO publie un opérateur K8s pour gérer des clusters multi-nœuds en mode distribué (haute dispo, erasure coding).
- Prefect — utilise MinIO comme storage block pour ses résultats de flows et ses artefacts (logs, plots générés par une tâche).
Un seul conteneur MinIO suffit pour dev, perso, ou petite équipe. En production sérieuse, on déploie un cluster multi-nœuds avec erasure coding : MinIO découpe chaque objet en morceaux avec redondance, ce qui permet de perdre plusieurs disques sans perdre les données. C'est ce qui rend MinIO viable en alternative à S3 pour des gros volumes.
Pour aller plus loin
- Site officiel : min.io
- Documentation : min.io/docs
- Client Python officiel : github.com/minio/minio-py
- Documentation API S3 (AWS, qui sert de référence) : docs.aws.amazon.com/AmazonS3
- Console de démo en ligne : play.min.io