Module 4 — Environnements et images conteneurisées
Les données sont prêtes. Reste à décrire l'univers dans lequel elles seront traitées : version de Python, bibliothèques, éventuel binaire système. Azure ML matérialise cette description sous forme d'environment — un objet versionné qui produit, à l'usage, une image de conteneur stockée dans l'Azure Container Registry (ACR) du workspace. C'est cette image qui tourne sur les grappes du module 2, à l'identique en dev et en production.
Deux familles à ne pas confondre
Azure ML expose deux catégories d'environnements :
- Environnements organisés (
curated) : maintenus par Microsoft, préconstruits, préfixeAzureML-. Exemples utiles :AzureML-sklearn-1.5,AzureML-tensorflow-2.16-cuda12,AzureML-pytorch-2.4-cuda12. Ils tirent instantanément et couvrent la plupart des besoins standard. - Environnements personnalisés (
custom) : construits à partir d'un fichierconda.yml, d'unDockerfile, ou d'une combinaison des deux. À utiliser dès qu'une bibliothèque, une version ou un binaire système sort du standard.
Pour le fil rouge, un environnement organisé AzureML-sklearn-1.5 suffirait au modèle de base. Mais nous voulons xgboost en version précise et mlflow avec pyfunc, ce qui pousse à un environnement personnalisé.
Le fichier conda.yml : lisible et suffisant dans 80 % des cas
name: env-prev-demande
channels:
- conda-forge
dependencies:
- python=3.11
- pip=24.2
- pip:
- scikit-learn==1.5.2
- xgboost==2.1.1
- pandas==2.2.3
- pyarrow==17.0.0
- mlflow==2.16.2
- azureml-mlflow==1.57.0
Deux règles à graver :
- Toutes les versions sont épinglées avec
==. Unxgboostsans version installe la dernière compatible, différente demain, et la reproductibilité s'évapore. - La bibliothèque
azureml-mlflowdoit apparaître dès qu'on veut que les journauxMLflowremontent auworkspace. Sans elle, le suivi tourne mais n'atterrit nulle part.
L'enregistrement est atomique :
az ml environment create --name env-prev-demande --version 1 \
--conda-file conda.yml \
--image mcr.microsoft.com/azureml/openmpi5.0-ubuntu22.04:latest
L'image de base est une image Ubuntu fournie par Microsoft, avec les pilotes CUDA le cas échéant. Le fichier conda.yml s'y superpose.
Passer au Dockerfile : quand et pourquoi
Un fichier conda.yml ne peut pas installer un binaire système comme libgeos-dev. Le passage au Dockerfile s'impose dès que le projet a une dépendance native :
FROM mcr.microsoft.com/azureml/openmpi5.0-ubuntu22.04:latest
RUN apt-get update && apt-get install -y --no-install-recommends \
libgeos-dev libspatialindex-dev \
&& rm -rf /var/lib/apt/lists/*
COPY conda.yml /tmp/conda.yml
RUN conda env update --name base --file /tmp/conda.yml \
&& conda clean -afy
az ml environment create --name env-prev-demande --version 2 \
--build-context ./env/ --dockerfile-path Dockerfile
Azure ML construit l'image dans le cloud (build context) puis la publie dans l'ACR du workspace. La première construction prend 6 à 12 minutes ; les suivantes, si le Dockerfile ne change pas de ligne, bénéficient du cache de couches et prennent quelques secondes.
Versionnage strict : jamais de mutation
Un environnement enregistré est immuable. Modifier une dépendance impose une nouvelle version.
az ml environment create --name env-prev-demande --version 3 \
--conda-file conda.yml
Cette contrainte est structurante. Elle protège la reproductibilité des tâches passées : rejouer la tâche du 12 janvier avec env-prev-demande:1 produira exactement la même image, même si xgboost 2.1.1 a été depuis retiré de PyPI. C'est ce qui distingue Azure ML d'un pip install pris à la volée dans un notebook.
Certains guides suggèrent d'utiliser --set-default-version ou de référencer azureml:env-prev-demande@latest dans les tâches. Cela fonctionne — jusqu'au jour où quelqu'un pousse une version 4 et où la production casse silencieusement à la prochaine exécution planifiée. La règle est : dans une définition de tâche de production, toujours référencer azureml:env-prev-demande:3, avec le numéro explicite. L'alias latest n'est qu'un outil de développement.
Construction et cache : quelques gestes qui accélèrent
- Ordonner le
Dockerfiledu moins volatil au plus volatil : couches système d'abord,conda.ymlensuite, code applicatif jamais dans l'image d'environnement (le code voyage avec la tâche) - Verrouiller également les versions apt dans les cas critiques (
libgeos-dev=3.12.1-3build1) pour les projets qui ont vécu la mise à jour surprise d'une dépendance native - Purger l'espace disque de conda dans une seule couche (
conda clean -afyen fin deRUN) pour ne pas gonfler l'image - Éviter les images de base publiques non-Microsoft : elles ne sont pas garanties de contenir les paquets attendus par les points de terminaison en ligne du module 8
En résumé
- Curated pour un besoin standard, custom dès qu'une version précise ou un binaire système est en jeu
- Épingler toutes les dépendances Python et inclure
azureml-mlflowpour que le suivi remonte - Un
Dockerfileavec cache de couches pour les dépendances système ; le code applicatif reste hors image - Toujours référencer un numéro de version explicite en production, jamais
latestou@latest
Le module suivant lance la première tâche d'entraînement dans cet environnement et fait remonter les journaux via MLflow.