Vous avez peut-être déjà rencontré ce décalage : une fonction de quelques centaines de lignes est emballée dans une image, accompagnée d’un environnement complet, puis démarrée comme une application beaucoup plus lourde qu’elle ne l’est réellement. Le conteneur reste pratique, mais il n’est pas toujours la plus petite unité utile. WebAssembly côté serveur pose une autre question : que se passe-t-il si l’on déploie seulement le code, avec les accès strictement nécessaires ? WASI rend cette idée exploitable. Pas partout, et pas encore sans compromis.
Vous avez peut-être déjà rencontré ce décalage : une fonction de quelques centaines de lignes est emballée dans une image, accompagnée d’un environnement complet, puis démarrée comme une application beaucoup plus lourde qu’elle ne l’est réellement. Le conteneur reste pratique, mais il n’est pas toujours la plus petite unité utile. WebAssembly côté serveur pose une autre question : que se passe-t-il si l’on déploie seulement le code, avec les accès strictement nécessaires ? WASI rend cette idée exploitable. Pas partout, et pas encore sans compromis.
Le vrai sujet n’est pas de remplacer Docker
La comparaison entre WebAssembly et les conteneurs commence souvent par une mauvaise question : lequel va gagner ? Elle pousse à chercher un vainqueur général, alors que les deux technologies ne décrivent pas exactement la même unité de déploiement.
Un conteneur est une enveloppe opérationnelle familière pour une application et son environnement d’exécution. Il s’insère dans des chaînes déjà bien établies : construction d’images, registres, orchestration, réseau, journaux et politiques d’exécution. Cette généralité explique sa place dans les architectures modernes.
WebAssembly, lui, est d’abord un format d’exécution portable. Côté serveur, il devient intéressant lorsqu’un module doit exécuter une tâche précise sans recevoir tout l’environnement d’un système. WASI, ou WebAssembly System Interface, fournit alors des interfaces pour interagir avec des ressources extérieures au module.
La différence éditorialement importante est donc la suivante : Wasm cherche à réduire l’unité d’exécution, tandis que le conteneur reste une enveloppe généraliste. Une fonction courte, un filtre, un plugin ou une commande portable n’a pas nécessairement les mêmes besoins qu’une application Linux complète.
Cette distinction évite deux erreurs symétriques. La première consiste à présenter WASI comme un remplacement universel des conteneurs. La seconde consiste à le considérer comme une simple curiosité de runtime, sans voir ce que change un environnement plus petit et plus contrôlé.
Ne demandez pas si Wasm va remplacer Docker. Demandez quelle est la plus petite unité d’exécution dont votre workload a réellement besoin.
WASI remplace l’accès implicite par des capacités choisies
Le mécanisme central de WASI est le modèle de capacités. Une capacité désigne ici une autorisation concrète accordée par l’hôte : par exemple, l’accès à une ressource ou à une interface déterminée. Le module ne reçoit pas automatiquement la totalité du système.
La documentation de WASI décrit un modèle où les ressources sont accessibles via des interfaces et des capacités fournies par l’environnement d’exécution. Cela tranche avec une conception dans laquelle le programme pourrait supposer la présence d’un système de fichiers, d’appels système ou d’un réseau selon les conventions de la machine hôte.
Le bénéfice est autant architectural que sécuritaire. L’équipe qui lance le module peut définir ce qu’il est autorisé à faire, puis conserver cette frontière lorsque le même module change d’environnement. Le code est ainsi séparé des décisions d’intégration prises par l’hôte.
Cette séparation ne signifie pas que toute exécution Wasm est automatiquement sûre. Le runtime, ses interfaces, sa configuration et le code qui lui fournit les ressources restent déterminants. La documentation de Wasmtime présente d’ailleurs la sécurité comme un modèle combinant isolation mémoire, contrôle des imports et capacités accordées au module.
WASI Preview 2 et le Component Model prolongent cette direction. Le modèle de composants cherche à organiser des interfaces composables entre modules et langages, tout en améliorant la virtualisabilité de l’environnement. Mais le dépôt officiel de WASI reste celui d’une spécification en développement : les interfaces et leur niveau de maturité ne sont pas uniformes.
Pour une équipe, la conséquence est pratique. Il ne suffit pas de demander si un langage compile vers WebAssembly. Il faut inventorier les ressources utilisées par le programme, identifier les interfaces WASI disponibles et vérifier si le runtime choisi sait réellement les fournir dans le contexte cible.
Deux modèles d’exécution
WASI expose au module des interfaces et des capacités choisies par l’hôte.
Un conteneur fournit généralement un environnement plus proche d’un système Linux complet, avec un accès opérationnel plus direct aux outils et ressources attendus par l’application.
L’isolation devient concrète avec les plugins et le code non fiable
Le terrain le plus convaincant pour Wasm n’est pas forcément celui d’une application monolithique. C’est souvent celui où l’on veut exécuter du code que l’on ne souhaite pas laisser circuler librement dans le processus ou sur la machine.
WebAssembly isole la mémoire des instances. Les interactions avec l’extérieur passent par des imports et des exports, c’est-à-dire des fonctions ou interfaces explicitement exposées par l’hôte ou par le module. Cette contrainte forme une frontière claire pour exécuter un plugin, une règle métier fournie par un tiers ou une fonction dont le comportement doit rester limité.
Imaginez un outil qui accepte des extensions pour transformer des documents. Une extension peut avoir besoin de lire ses données d’entrée et de produire un résultat, mais pas d’explorer le système de fichiers, d’ouvrir une connexion réseau ou d’accéder à des secrets. Avec un module WASI, l’hôte peut concevoir l’exécution autour de ces seules capacités.
Le même raisonnement s’applique à certains services edge ou fonctions courtes. Le code reçoit un contexte étroit, accomplit une opération, puis s’arrête. Plus le contrat est petit, plus il est possible de contrôler ce qui entre et ce qui sort.
Un conteneur peut lui aussi être durci et isolé. Il dispose toutefois d’un modèle opérationnel généralement plus proche d’un environnement Linux, avec davantage de composants et de conventions à configurer. La comparaison ne porte donc pas sur une opposition entre sécurité et absence de sécurité, mais sur la forme de la frontière imposée au code.
Cette frontière est particulièrement utile quand plusieurs équipes ou plusieurs fournisseurs livrent des composants dans une même plateforme. Elle ne supprime pas la nécessité de vérifier les modules, de limiter les ressources et de surveiller les exécutions. Elle rend simplement les autorisations plus explicites dans le contrat entre l’hôte et le code invité.
Le cas du plugin non fiable
Un logiciel peut charger un plugin sans lui donner un accès implicite au système de fichiers, au réseau ou à d’autres ressources. L’hôte choisit les interfaces réellement disponibles.
Le démarrage rapide dépend de la taille réelle du workload
Les démarrages rapides sont souvent présentés comme l’avantage évident de WebAssembly côté serveur. L’intuition est solide : un module ciblé peut demander moins d’environnement à initialiser qu’une application qui attend un système plus complet. Mais cette intuition ne suffit pas à prédire un résultat de production.
Des travaux expérimentaux ont étudié WebAssembly dans des contextes serverless et comparé plusieurs runtimes côté serveur. Ils soutiennent l’intérêt de Wasm pour les fonctions courtes et les cold starts, tout en rappelant que les bénéfices varient selon le runtime, le workload et le chemin d’intégration.
Un module exécuté directement par un runtime n’a pas le même profil qu’un module Wasm placé derrière plusieurs couches. Si l’on ajoute une couche de conteneurisation, d’adaptation ou d’orchestration, une partie du gain potentiel peut disparaître. Le format du code ne suffit donc pas à produire une latence faible.
Il faut aussi distinguer le démarrage du calcul lui-même. Une fonction peut s’initialiser rapidement, puis attendre une ressource externe, une interface réseau ou un service distant. Dans ce cas, réduire le temps de lancement du module ne réduit pas nécessairement la durée totale de la requête.
La bonne méthode consiste à mesurer le chemin complet. Combien de temps faut-il pour charger le module ? Quelle quantité de mémoire le runtime réserve-t-il ? Quel est le coût de l’hôte qui fournit les interfaces ? Que devient le résultat lorsque l’exécution est répétée ou conservée en mémoire ?
Cette approche est moins spectaculaire qu’une comparaison de chiffres isolés, mais elle est plus utile. Pour une fonction appelée rarement, le démarrage peut dominer le coût. Pour une tâche longue, le temps d’initialisation peut peser beaucoup moins que les entrées-sorties ou le calcul. Wasm est surtout crédible lorsque la forme du workload correspond à sa promesse de petite unité portable.
Un profilage en trois zones
La documentation Wasmtime décrit un profilage pouvant distinguer le code WebAssembly, l’hôte Wasmtime et potentiellement le noyau. Cette séparation aide à localiser le coût réel d’une exécution.
SourceLa performance se lit aussi dans l’empreinte et le runtime
La taille apparente d’un artefact ne décrit pas à elle seule la consommation réelle. Un module léger peut être lancé dans un runtime qui mobilise d’autres ressources. À l’inverse, une image de conteneur peut déjà être optimisée et bénéficier d’un environnement largement amorti par la plateforme.
La question intéressante n’est donc pas seulement « combien pèse le fichier ? ». Il faut regarder l’empreinte du processus, le nombre d’instances, la réutilisation du runtime, la fréquence des démarrages et les ressources nécessaires aux interfaces exposées.
Les travaux sur les usages serverless de WebAssembly montrent pourquoi les fonctions courtes et les démarrages sont un terrain d’étude pertinent. Ils ne démontrent pas une supériorité générale de Wasm. Ils mettent plutôt en évidence une possibilité : réduire le coût d’une exécution lorsque le code n’a pas besoin d’un environnement riche.
Wasmtime peut fonctionner comme runtime autonome ou être intégré comme bibliothèque. Cette double forme est importante. Une plateforme peut choisir de lancer directement les modules, ou d’embarquer le moteur dans un service qui garde le contrôle du cycle de vie, des limites et des interfaces.
Cette flexibilité a un revers : elle multiplie les décisions d’architecture. Il faut choisir le mode d’exécution, définir les limites de ressources, organiser le chargement des composants et décider comment les modules seront versionnés. La portabilité du format ne rend pas automatiquement portable toute la plateforme qui l’entoure.
La performance devient donc un sujet de contexte. Wasm peut être très pertinent pour une opération courte qui s’exécute souvent avec peu de capacités. Il est moins évident lorsqu’il faut reproduire un environnement complet, utiliser des dépendances système nombreuses ou maintenir un processus long avec des interactions variées.
Observer un module demande de regarder au-delà du code
Une technologie peut être rapide et rester difficile à exploiter. En production, l’équipe doit savoir ce qui consomme du temps, où la mémoire est mobilisée, pourquoi une requête attend et quelle couche porte la responsabilité.
Wasmtime propose des outils de profilage capables de distinguer le code WebAssembly, l’hôte Wasmtime et, potentiellement, le noyau. Cette séparation est utile parce qu’un ralentissement attribué au module peut en réalité venir d’une interface fournie par l’hôte ou d’une opération système.
Pour une équipe d’exploitation, ce découpage apporte un début de réponse à une question classique : le problème est-il dans le code invité ou dans le pont qui lui donne accès au monde extérieur ? Le diagnostic ne devient pas automatique, mais il peut être plus précis.
Il reste nécessaire de construire les conventions autour du runtime. Les journaux, les identifiants de requête, les métriques d’instance et les limites d’exécution doivent être transmis ou exposés par l’hôte. WASI ne remplace pas une stratégie d’observabilité ; il fournit un cadre dans lequel cette stratégie peut être intégrée.
Les conteneurs disposent, eux, d’un écosystème opérationnel très répandu. Les outils de déploiement, de supervision et de diagnostic savent déjà traiter leurs processus, leurs réseaux et leurs images. Ce capital d’exploitation compte, surtout pour une organisation qui doit rendre des incidents compréhensibles à plusieurs équipes.
Le choix peut donc basculer en faveur du conteneur même lorsque Wasm semble plus compact. Une plateforme qui sait déjà déployer, surveiller et restaurer des conteneurs doit mesurer le coût d’introduire un nouveau runtime, de nouvelles interfaces et de nouveaux chemins de diagnostic.
Le mode hybride n’est pas automatiquement gagnant
Docker présente son intégration des workloads Wasm comme bêta et indique qu’elle est dépréciée, avec une disparition annoncée d’une future version de Docker Desktop. L’enveloppe d’exploitation compte autant que le format du module.
Les conteneurs gardent l’avantage dès que le système devient riche
WASI devient une alternative crédible lorsque l’application peut vivre avec un contrat étroit. La situation change lorsque le programme dépend d’un système de fichiers complexe, d’un réseau sophistiqué, de périphériques, de bibliothèques natives ou d’un ensemble d’outils Linux déjà intégré.
Les interfaces WASI ne sont pas toutes au même niveau de maturité. Le dépôt officiel et les travaux autour de Preview 2 et du Component Model montrent un écosystème actif, mais aussi en évolution. Certaines interfaces, notamment autour de HTTP selon les indications fournies, restent expérimentales.
Cette évolution n’interdit pas l’usage de Wasm. Elle oblige à vérifier le périmètre exact du runtime et à accepter qu’une interface puisse évoluer. Pour un workload critique, la question n’est pas seulement de savoir si une démonstration fonctionne, mais si le contrat technique est suffisamment stable pour être maintenu.
Les conteneurs sont également plus directs pour les applications conçues autour d’un environnement Linux complet. L’équipe peut y retrouver les dépendances, les outils et les habitudes d’exploitation qu’elle utilise déjà. Cette continuité réduit parfois le risque global, même si l’enveloppe est plus lourde.
Les modes hybrides méritent une prudence particulière. Docker documente l’exécution de workloads Wasm comme une fonctionnalité bêta et précise que cette intégration est dépréciée, avec une disparition annoncée d’une future version de Docker Desktop. Cela ne condamne pas Wasm, mais rappelle qu’un emballage pratique peut ne pas constituer une stratégie durable.
Le choix doit donc porter sur la chaîne entière : compilation, distribution, runtime, accès aux ressources, observabilité, sécurité et gestion des versions. Un module très portable ne le reste pas forcément si son application dépend d’une interface spécifique ou d’une couche d’intégration fragile.
Une règle simple peut aider. Choisissez Wasm lorsque vous pouvez décrire clairement le contrat d’exécution et limiter les capacités. Choisissez un conteneur lorsque le workload demande surtout un environnement riche, des dépendances existantes et une exploitation déjà maîtrisée.
Conclusion : choisir la plus petite unité qui tient vraiment
WebAssembly côté serveur n’a pas besoin de remplacer les conteneurs pour devenir utile. Sa valeur apparaît dans des situations plus précises : exécuter du code non fiable, distribuer un plugin, lancer une fonction courte, déplacer un outil entre environnements ou servir une charge edge qui ne justifie pas un système complet.
WASI apporte alors une idée structurante : l’hôte ne remet pas implicitement les clés de la machine au module. Il lui fournit des interfaces et des capacités déterminées, tandis que WebAssembly protège la mémoire de l’instance et encadre les échanges avec l’extérieur.
Le bénéfice potentiel porte aussi sur le démarrage, l’empreinte et la portabilité. Mais ces avantages restent dépendants du runtime, de l’intégration et de la forme du workload. Les études disponibles sur le serverless éclairent certains scénarios ; elles ne permettent pas de conclure à une supériorité générale.
Les conteneurs conservent une place solide dès qu’une application attend un environnement Linux riche, des accès système variés, un réseau complexe ou un outillage opérationnel mature. Leur généralité est parfois exactement ce dont l’équipe a besoin.
La décision la plus saine commence donc par le workload, pas par la technologie préférée. Quelle est la plus petite unité d’exécution nécessaire ? Quelles ressources doit-elle recevoir ? Quelle interface peut rester stable ? Qui saura diagnostiquer une panne à trois heures du matin ?
Si les réponses dessinent un contrat court, contrôlé et portable, WASI mérite un essai mesuré. Si elles décrivent une application qui attend le système entier, le conteneur reste probablement l’enveloppe la plus honnête. La complémentarité n’est pas un compromis par défaut : c’est ici la conclusion la plus solide.
Sources
- Capabilities.md — WebAssembly
- WebAssembly System Interface — WebAssembly
- Security — Bytecode Alliance
- Introduction - Wasmtime — Bytecode Alliance
- Profiling WebAssembly — Bytecode Alliance
- On the Use of Web Assembly in a Serverless Context — Tomasz B. et al.
- Wasm workloads — Docker
Équipe Daymain