Construire son propre worker GPU avec Docker, pas à pas
Ou : comment faire entrer un modèle d’IA dans une boîte qui s’allume toute seule quand on frappe à la porte.
La réponse courte : un worker serverless Runpod, c’est un fichier Python et un Dockerfile. Le fichier définit une fonction qui reçoit la requête et renvoie le résultat, et l’enregistre avec runpod.serverless.start(). Le Dockerfile installe le SDK et vos dépendances, et intègre de préférence le modèle. Vous testez en local, construisez l’image pour linux/amd64, la poussez sur un registre ou laissez Runpod la construire depuis GitHub, puis créez l’endpoint. C’est l’étape qui transforme un modèle en service dans une architecture de pods et workers GPU.
Avant d’écrire une ligne, un détour par le Hub de Runpod s’impose. Il propose des workers prêts à déployer en quelques clics, ComfyUI, vLLM pour les modèles de langage, faster-whisper pour la transcription, et bien d’autres publiés par la communauté. Sur ce site, le worker vidéo WAN 2.2 vient d’un dépôt tiers et le worker de transcription du dépôt officiel de Runpod. Écrire son propre worker ne se justifie que pour un modèle ou un traitement qu’aucun de ceux-là ne couvre.
Le principe de base, lui, tient dans la documentation des handlers : votre fonction reçoit un objet job dont le champ input contient ce que le client a envoyé. Tout ce qui est coûteux, le chargement du modèle surtout, se fait en dehors de cette fonction, au démarrage du worker, pour ne pas le répéter à chaque requête.
Pour qui : un développeur Python qui veut servir un modèle ou un traitement GPU qu’aucun worker du Hub ne propose, en payant la carte à la seconde.
À partir de : 0,00031 $ la seconde de RTX 4090 en serverless, rien quand aucune requête n’arrive ; la construction depuis GitHub ne consomme pas de carte graphique.
Pour démarrer : ouvrir un compte Runpod, publier l’image sur un registre ou connecter le dépôt GitHub, et créer l’endpoint depuis la console.
Worker serverless GPU avec Docker : du handler à l’endpoint
Le handler d’abord, dans un fichier handler.py :
| |
Il se teste sans carte graphique ni compte, en local : python handler.py --test_input '{"input": {"prompt": "test"}}' exécute un job, et python handler.py --rp_serve_api lance un petit serveur sur le port 8000 pour l’interroger comme un vrai endpoint. Un fichier test_input.json placé à côté du handler est lu automatiquement.
Le Dockerfile ensuite. Celui du démarrage rapide de Runpod est volontairement minimal :
| |
Pour un vrai modèle, deux changements s’imposent : une image de base avec CUDA, et le téléchargement du modèle pendant la construction, dans une instruction RUN, pour qu’il soit sur le disque de la machine avant le démarrage du worker. C’est le levier le plus efficace contre le démarrage à froid quand le modèle ne vient pas de Hugging Face. L’image se construit obligatoirement pour linux/amd64, ce qui compte sur un Mac récent, avec docker build --platform linux/amd64, puis se pousse sur un registre avec une étiquette de version. Runpod déconseille :latest en production : des workers peuvent continuer à utiliser l’ancienne version gardée en cache.
Reste le déploiement, par l’une des deux voies. Depuis un registre, vous indiquez l’adresse de l’image à la création de l’endpoint. Depuis GitHub, Runpod construit l’image lui-même à chaque nouvelle version publiée du dépôt, avec des limites à connaître : 160 minutes de fenêtre de construction au total, 30 minutes pour l’étape docker build, une image de 80 Go au plus, pas de carte graphique pendant la construction, et une image qui ne peut pas sortir de Runpod.
Pour ComfyUI, le plus simple est de partir de l’image officielle plutôt que d’un Dockerfile vierge. Le dépôt worker-comfyui publie des images prêtes, de la version de base sans modèle à des versions qui embarquent Flux ou SDXL, entre 15 et 38 Go. Pour ajouter vos nœuds et vos modèles, un Dockerfile de quelques lignes suffit :
| |
Le worker reçoit alors un workflow exporté depuis ComfyUI au format API, avec d’éventuelles images en base64, et renvoie les images produites en base64 ou sur un stockage S3.
Si votre worker démarre lentement
Un modèle intégré à l’image démarre plus vite qu’un modèle lu sur un volume, mais d’autres réglages comptent aussi. Ils sont classés dans raccourcir le démarrage à froid.
Si vous préférez garder les modèles hors de l’image
Pour des modèles qui changent souvent, un volume réseau évite de reconstruire l’image à chaque fois. Son prix et ses contraintes de centre de données sont dans ranger ses modèles sur un volume.
Si vos jobs durent plusieurs minutes
Un worker qui génère de la vidéo se pilote en asynchrone, avec une boucle d’attente ou un webhook. La mécanique est détaillée dans les jobs longs sur GPU serverless.