Aller au contenu
English
Compte : non connecté, synchronisation possible Mon apprentissage
Selectionner le thème
English

DVC : versionner ses données avec un stockage S3

Par mis à jour le

Améliorer cette page

DVC (Data Version Control) versionne les données comme Git versionne le code, sans mettre les données dans Git. Il écrit dans le dépôt un petit fichier pointeur qui contient l'empreinte du jeu, et envoie le jeu lui-même dans un stockage objet S3. Revenir à un ancien commit Git permet alors de retrouver, octet pour octet, les données qui allaient avec.

Cette leçon fait suite à celle sur le projet reproductible : le code, la graine et les bibliothèques sont fixés, il reste la source de variation la plus traître, les données. Public : intermédiaire. On y suit un fichier avec dvc add, on le pousse dans un bucket Garage, on le restitue sur un clone vierge, puis on retrouve une version antérieure.

  • Expliquer pourquoi Git ne convient pas aux données volumineuses et ce que DVC y ajoute.
  • Suivre un fichier avec dvc add et lire le pointeur qu'il écrit.
  • Configurer un remote S3 sans mettre les clés d'accès dans le dépôt.
  • Pousser et récupérer un jeu avec dvc push et dvc pull.
  • Retrouver une version antérieure d'un jeu par git checkout puis dvc checkout.
  • Contrôler que cache local, bucket et dépôt sont synchronisés avec dvc status.

La leçon suppose la leçon sur le projet reproductible (uv, empreinte SHA-256, .gitignore) et la pratique de Git avec un dépôt distant (collaborer avec des remotes). Il faut aussi Docker, car le lab fournit un stockage S3 local sous forme de conteneur. Un bucket S3 est un espace de stockage objet adressé par un nom ; Garage en est une implémentation légère, et le comparatif S3 aide à choisir en production. Les versions mesurées : DVC 3.67.1, dvc-s3 3.3.0, Garage v2.4.1.

Git est conçu pour de petits fichiers texte dont chaque version se compare ligne à ligne ; un jeu de données lourd ou binaire le fait gonfler sans rien lui apprendre. Chaque nouvelle version du fichier alourdit l'historique, tout clone télécharge cet historique en entier, et personne ne peut relire un diff de plusieurs millions de lignes de CSV.

DVC garde de Git ce qu'il fait bien (l'historique, les branches, le lien avec le commit) et déplace ailleurs ce qui pèse. Le dépôt ne contient plus que le fichier pointeur, quelques lignes de texte qui désignent le contenu par son empreinte. Les données, elles, vont dans un remote, ici un bucket S3. Le pointeur est versionné avec le code : le commit qui change le code et le commit qui change le jeu sont donc les mêmes, et un git checkout suffit à dire « donne-moi les données de ce moment-là ».

Comment DVC, Git et S3 se partagent-ils le travail ?

Section intitulée « Comment DVC, Git et S3 se partagent-ils le travail ? »

Le fichier de données reste sur le poste mais Git l'ignore ; Git reçoit le pointeur et la configuration du remote, S3 reçoit le contenu. Trois emplacements, trois rôles, et une empreinte qui les relie.

Sur le schéma, dvc add copie le fichier dans le cache local (.dvc/cache). Suivez les flèches épaisses : dvc push envoie ce cache vers le bucket, dvc fetch remplit le cache depuis le bucket, et dvc checkout restitue le fichier dans le poste. dvc pull enchaîne les deux : fetch puis checkout, d'où le « 1 file fetched and 1 file added » qu'il affiche. La flèche pointillée est celle de Git : le clone récupère le pointeur, jamais les données. C'est pourquoi un clone sans dvc pull n'a pas le jeu.

Le fichier data/metriques.csv, ignoré par Git, est suivi par dvc add : celui-ci écrit le pointeur metriques.csv.dvc et copie le fichier dans le cache local .dvc/cache. Le pointeur et la configuration partent dans le dépôt Git par git commit. Le cache part dans le bucket S3 par dvc push ; dvc fetch remplit le cache depuis le bucket et dvc checkout restitue le fichier, dvc pull enchaînant les deux. Un git clone ne récupère que le pointeur.Poste de travaildvc addgit commitdvc adddvc pushgit clonedvc fetchdvc checkout, inclus dans dvcpulldata/metriques.csv(ignoré par Git)metriques.csv.dvcempreinte MD5cache local.dvc/cacheDépôt Gitpointeur + .dvc/configBucket S3dvc-donnees
Source · SVG
Échap pour fermer, + et − pour zoomer, défilement pour se déplacer. 100 %

dvc add calcule l'empreinte du fichier, le copie dans le cache local de DVC (.dvc/cache), écrit le pointeur et demande à Git d'ignorer le fichier. On l'exécute après avoir installé DVC dans l'environnement uv (uv add dvc dvc-s3, le second paquet apportant le support S3), puis initialisé Git et DVC dans le projet :

Fenêtre de terminal
uv add dvc dvc-s3
git init
uv run dvc init
mkdir -p data
uv run python genere-metriques.py --graine 42 --lignes 5000 --sortie data/metriques.csv
sed -i '/^data\/metriques.csv$/d' .gitignore
uv run dvc add data/metriques.csv

Le mkdir -p data est indispensable : le générateur n'écrit pas dans un dossier absent. Le sed retire du .gitignore racine la ligne posée dans la leçon précédente : le CSV change de propriétaire, c'est maintenant DVC qui l'ignore. Si la ligne reste, dvc add réussit sans message, mais il n'écrit pas le data/.gitignore, et le git add data/.gitignore plus bas échoue avec fatal: pathspec 'data/.gitignore' did not match any files.

dvc init crée le répertoire .dvc/ avec la configuration, qui se versionne. dvc add écrit le pointeur data/metriques.csv.dvc et ajoute le fichier de données à un data/.gitignore. Le pointeur a cette forme :

outs:
- md5: <empreinte MD5 du fichier>
size: <taille en octets>
hash: md5
path: metriques.csv

DVC identifie les fichiers par une empreinte MD5, différente du SHA-256 que le lab utilise pour ses vérifications : les deux désignent le même contenu, mais seule la première est écrite dans le pointeur. C'est ce pointeur, et non le CSV, qui entre dans Git.

Comment configurer un remote S3 sans mettre les clés dans le dépôt ?

Section intitulée « Comment configurer un remote S3 sans mettre les clés dans le dépôt ? »

Le remote est déclaré dans .dvc/config (adresse, région, point d'accès), les clés viennent de l'environnement. Le dépôt peut ainsi voyager avec sa configuration sans jamais porter un secret. Pour le bucket Garage du lab :

Fenêtre de terminal
uv run dvc remote add -d stockage s3://dvc-donnees
uv run dvc remote modify stockage endpointurl http://127.0.0.1:3900
uv run dvc remote modify stockage region garage

L'option -d fait de stockage le remote par défaut. Le point d'accès (endpointurl) est nécessaire parce que le stockage n'est pas AWS ; la région garage est celle que le conteneur Garage déclare. Les clés d'accès se fournissent par les variables AWS_ACCESS_KEY_ID et AWS_SECRET_ACCESS_KEY, que DVC, MLflow et boto3 lisent telles quelles. Le lab les met dans un fichier .env généré, ignoré par Git, que le script scripts/socle-demarrer.sh crée en même temps qu'il démarre le stockage (voir « Mettre en pratique »). Dans le terminal où vous lancez DVC, chargez-le ainsi, <catalogue> désignant le dossier du catalogue de labs :

Fenêtre de terminal
set -a && . <catalogue>/shared/socle/.env && set +a

Ces variables n'existent que dans ce terminal : un nouveau terminal, ou un clone ouvert ailleurs, demande de refaire ce chargement.

Comment pousser le jeu et le retrouver sur un clone vierge ?

Section intitulée « Comment pousser le jeu et le retrouver sur un clone vierge ? »

On commite le pointeur, puis dvc push envoie le contenu au bucket ; un clone récupère ensuite le pointeur par Git et le contenu par dvc pull. Ces deux gestes sont indissociables : un commit sans push laisse un pointeur qui ne désigne rien d'accessible aux autres.

Fenêtre de terminal
git add data/metriques.csv.dvc data/.gitignore .dvc pyproject.toml uv.lock genere-metriques.py .gitignore
git commit -m "Jeu de données, graine 42"
uv run dvc push

Le commit embarque aussi le verrou uv.lock : sans lui, le clone ne saurait pas quel environnement reconstruire. Après le commit, git status ne doit lister aucun fichier. Sur le lab, dvc push annonce un fichier poussé. Sur un autre poste, ou dans un dossier neuf (avec les variables d'accès chargées, comme plus haut) :

Fenêtre de terminal
git clone <depot> clone && cd clone
uv run dvc pull
sha256sum data/metriques.csv

dvc pull annonce un fichier récupéré, et l'empreinte SHA-256 doit être celle mesurée avant le push : 550be1a3… pour la graine 42. C'est la preuve que le clone a les octets exacts, pas seulement un fichier du même nom.

Comment retrouver une version antérieure du jeu ?

Section intitulée « Comment retrouver une version antérieure du jeu ? »

Chaque commit Git désigne, par son pointeur, une version précise des données : revenir au commit revient aux données. Le scénario du lab est celui d'un jeu régénéré avec une autre graine. On suit la nouvelle version comme la première, dans un second commit :

Fenêtre de terminal
uv run python genere-metriques.py --graine 43 --lignes 5000 --sortie data/metriques.csv
uv run dvc add data/metriques.csv
git add data/metriques.csv.dvc
git commit -m "Jeu de données, graine 43"
uv run dvc push

Le jeu de la graine 43 a une empreinte SHA-256 qui commence par 65e665e5. Le bucket contient maintenant deux versions. Pour revenir à la première :

Fenêtre de terminal
git checkout <commit-graine-42>
uv run dvc checkout

git checkout remet l'ancien pointeur (Git signale un HEAD détaché, sans gravité : git switch - revient ensuite à la branche), dvc checkout remplace le fichier de données par la version qu'il désigne, prise dans le cache local. Sur un clone vierge qui n'a jamais eu cette version, c'est dvc pull qui la télécharge. Le retour à la graine 42 redonne l'empreinte 550be1a3…. La même procédure permet de retrouver, plus tard, le jeu qui a servi à entraîner un modèle donné : il suffit d'avoir le commit.

dvc status compare le dépôt au cache local, dvc status -c compare le cache au remote. Les deux réponses ne se ressemblent pas, et les confondre est une erreur courante : une sortie « up to date » ne dit rien du bucket.

CommandeCe qu'elle compareRéponse quand tout va bien
dvc statuspointeurs et fichiers du projetData and pipelines are up to date.
dvc status -ccache local et remoteCache and remote 'stockage' are in sync.

Le contenu du bucket se contrôle aussi côté Garage. Garage n'a pas de shell dans son conteneur : toute commande passe par docker compose exec depuis le dossier du socle. La commande docker compose exec -T garage /garage bucket info dvc-donnees affiche une ligne Objects: qui doit compter les objets des deux versions.

SymptômeCause probableCorrection
dvc pull échoue avec une erreur d'accèsVariables AWS_ACCESS_KEY_ID et AWS_SECRET_ACCESS_KEY absentes de l'environnementCharger le .env du socle avant la commande
dvc pull ne trouve pas le bucketendpointurl ou region manquant dans .dvc/configRelancer les deux dvc remote modify et commiter .dvc/config
Le clone n'a pas le fichier de donnéesdvc pull jamais lancé : Git ne transporte que le pointeurLancer dvc pull
dvc status -c signale des fichiers à pousserLe commit a été fait sans dvc pushLancer dvc push
git status montre data/metriques.csvLe fichier n'a pas été suivi par dvc addLancer dvc add, puis commiter pointeur et data/.gitignore
dvc add refuse un fichier déjà suivi par GitLe CSV est déjà dans l'historique Gitgit rm --cached data/metriques.csv et commiter, puis dvc add (DVC suggère git rm -r --cached)

Le lab part d'un jeu de graine 42 qui a été écrasé : il faut le mettre sous DVC avec un remote S3 Garage, conserver deux versions (graines 42 et 43) dans deux commits distincts, puis prouver qu'un clone vierge restitue le jeu courant par dvc pull et que le retour au premier commit restitue le jeu de graine 42. La validation lit le dépôt Git (qui doit rester propre), le contenu du bucket, dvc status et dvc status -c sans écart, et les empreintes des fichiers, jamais les commandes tapées. Avant dsoxlab run, lancez le script scripts/socle-demarrer.sh du catalogue, qui démarre Garage ; scripts/socle-arreter.sh l'arrête à la fin.

  • Git ne convient pas aux données lourdes ; DVC met un pointeur dans le dépôt et le contenu dans un remote.
  • dvc add suit le fichier, écrit fichier.dvc et fait ignorer le fichier par Git.
  • Un commit versionne le pointeur : revenir au commit, c'est revenir aux données.
  • dvc push envoie au remote, dvc pull récupère ; un commit sans push laisse les autres sans données.
  • Un remote S3 non AWS demande endpointurl et region dans .dvc/config ; les clés restent dans l'environnement.
  • dvc status ne dit rien du bucket : c'est dvc status -c qui compare cache et remote (in sync).
  • Retrouver une version : git checkout <commit> puis dvc checkout (ou dvc pull sur un clone qui ne l'a jamais eue).

Vérifiez que l'essentiel de ce guide est acquis. Les questions portent uniquement sur ce qui vient d'être expliqué ici.

Contrôle de connaissances

Validez vos connaissances avec ce quiz interactif

6 questions
6 min.
70% requis

Informations

  • Le chronomètre démarre au clic sur Démarrer
  • Questions à choix multiples, vrai/faux et réponses courtes
  • Vous pouvez naviguer entre les questions
  • Les résultats détaillés sont affichés à la fin

Lance le quiz et démarre le chronomètre

Ce projet vous est utile ?

Les guides, formations, quiz et labs restent gratuits. Si vous les utilisez régulièrement, vous pouvez contribuer à leur maintenance et à leur développement.

Devenir membre de soutien (nouvel onglet) Soutenir une fois (nouvel onglet) En savoir plus

Suivez aussi le projet sur LinkedIn