Apporter des workflows Docker Compose-style à Apple Container
Le projet container d’Apple est l’une des évolutions les plus intéressantes de l’écosystème de développement local de ces dernières années.
Pendant longtemps, exécuter des containers sur macOS a impliqué d’accepter une pile d’abstraction qui n’était pas réellement native de la plateforme : machines virtuelles, daemons, couches de partage de fichiers, couches réseau, puis outils de développement construits par-dessus.
Cela a fonctionné. Mais cela venait aussi avec des compromis.
Apple change la discussion avec container. Le projet est écrit en Swift, conçu pour Apple Silicon, et pensé pour exécuter des containers Linux comme des machines virtuelles légères sur macOS. Il reste compatible avec les images OCI, ce qui lui permet de s’intégrer à l’écosystème container existant au lieu de créer un monde fermé.
Mais il manquait une brique évidente pour le développement au quotidien : un container seul est utile, mais les vraies applications ne sont presque jamais composées d’un seul container.
La plupart des environnements modernes combinent plusieurs services : une API, une base de données, une queue, un worker, un reverse proxy, une stack de métriques ou un service de migration. Pour beaucoup d’équipes, docker compose up n’est pas juste une commande. C’est le point d’entrée du projet.
C’est pour cette raison que nous avons commencé container compose.
Le problème : les équipes ont besoin de composition
Le CLI container d’Apple donne déjà aux développeurs macOS une manière native de construire et d’exécuter des containers. C’est important.
Mais les workflows de développement ont besoin d’orchestration au niveau du projet.
Une application ne dit pas seulement :
run this imageElle dit plutôt :
démarre Postgresattends qu'il soit healthypuis démarre l'APImonte ces fichiersexpose ces portslance ce service seulement en mode debugscale ce workerstream les logs du projetarrête et nettoie tout proprementC’est cette couche que Docker Compose a rendue familière.
Notre objectif avec container compose est d’apporter ce type de workflow à l’écosystème container d’Apple, tout en restant alignés avec la manière dont le runtime Apple fonctionne réellement.
Pas un clone du daemon Docker.
Pas une couche Kubernetes complète.
Un plugin natif pour le CLI container d’Apple, capable de comprendre des workflows proches de Docker Compose.
Ce que nous avons construit
container compose est un plugin natif pour le CLI container d’Apple.
Il permet de démarrer, arrêter, inspecter et gérer des applications multi-containers depuis des fichiers Compose standards :
container system startcontainer compose up -f compose.yaml -p democontainer compose ps -p democontainer compose logs -p democontainer compose down -p demoL’intention est simple : conserver le workflow que les développeurs connaissent déjà, mais le faire fonctionner avec le runtime container d’Apple.
Le plugin supporte les commandes de cycle de vie attendues :
container compose upcontainer compose downcontainer compose pscontainer compose logscontainer compose execcontainer compose runcontainer compose configcontainer compose watchcontainer compose statsIl inclut aussi des workflows opérationnels comme la sauvegarde et le chargement d’une archive de stack pour des migrations hors ligne.
C’est important parce que le développement local ne consiste pas seulement à démarrer des containers. Il consiste à obtenir un environnement répétable : inspecter ce qui tourne, valider la configuration résolue, streamer les logs, exécuter des commandes dans les services, copier des fichiers, observer les ressources et supprimer proprement les ressources d’un projet.
Pourquoi un plugin, et pas un simple wrapper ?
Le chemin le plus simple aurait été d’écrire un wrapper autour de commandes shell.
Nous ne voulions pas seulement cela.
Un wrapper peut masquer la complexité pour une démo simple, mais il se casse vite quand les vrais workflows arrivent : ordre des dépendances, health checks, profiles, scaling, nommage des projets, substitution d’environnement, contexts machines, volumes, secrets et gestion des erreurs.
container compose est écrit en Swift et construit sur l’écosystème container d’Apple. Le package dépend de container, containerization, des packages Swift associés, ainsi que de swift-argument-parser et Yams pour le CLI et le parsing YAML.
Cela donne une base plus solide qu’un enchaînement de commandes opaques.
Le plugin peut parser et résoudre les fichiers Compose, construire un plan d’exécution, valider les contraintes tôt, puis piloter le runtime container de manière intentionnelle.
Le démarrage n’est pas juste “start everything”
L’une des parties les plus importantes d’une orchestration façon Compose est l’ordre de démarrage.
Démarrer dix containers dans un ordre aléatoire est facile. Les démarrer correctement est plus difficile.
container compose démarre les services par vagues de dépendances. Les services d’une même vague peuvent démarrer en parallèle. La vague suivante démarre seulement lorsque les exigences de dépendance précédentes sont satisfaites.
Par exemple :
services: db: image: postgres:16 healthcheck: test: ["CMD", "pg_isready"] interval: 5s timeout: 3s retries: 5
api: image: myapp:latest depends_on: db: condition: service_healthyDans ce cas, l’API ne doit pas démarrer simplement parce que le process de base de données existe. Elle doit démarrer quand la base est réellement healthy.
Le plugin supporte des conditions de dépendance comme service_started, service_healthy et service_completed_successfully. Cette dernière est particulièrement utile pour les services one-shot, comme les migrations.
C’est la différence entre un environnement local qui fonctionne souvent et un environnement local suffisamment déterministe pour une équipe.
Une sémantique de projet
Les workflows Compose ont besoin d’un modèle de projet.
Un projet définit la frontière qui permet à l’outil de savoir quels containers appartiennent ensemble. Sans cela, des commandes comme down, ps, logs ou stats deviennent fragiles.
container compose résout le nom du projet à partir du flag -p, de COMPOSE_PROJECT_NAME, du champ name: dans le fichier Compose ou du nom du dossier parent.
Cela signifie que :
container compose up -p democontainer compose logs -p democontainer compose down -p demoopère sur la même stack logique.
Les containers suivent une convention de nommage prévisible :
{project}_{service}_{index}Par exemple :
demo_web_1demo_web_2demo_db_1Cette prévisibilité compte pour le debug, les scripts et la transmission du projet à un autre développeur.
Résolution des fichiers Compose
Le plugin supporte les noms standards que les développeurs attendent :
compose.yamlcompose.ymldocker-compose.yamldocker-compose.ymlIl supporte aussi plusieurs fichiers :
container compose up -f base.yml -f production.ymlLes fichiers passés plus tard surchargent les précédents.
C’est essentiel pour les vrais projets, où une équipe peut avoir une stack de base, une surcharge de développement, une surcharge CI ou une surcharge locale.
Le plugin supporte aussi la substitution de variables depuis les fichiers .env et l’environnement shell :
image: ${IMAGE_NAME:-nginx:latest}Cela garde les fichiers Compose portables sans tout coder en dur.
Profiles, scaling et limites de ressources
Les stacks modernes contiennent souvent des services qui ne doivent pas démarrer tout le temps.
Un debugger, un exporter de métriques, une interface d’administration ou un helper local peuvent être utiles, mais seulement quand on les demande explicitement.
Les profiles répondent à ce besoin :
services: app: image: myapp:latest
debugger: image: mytools:latest profiles: [debug]Puis :
container compose updémarre l’application par défaut, tandis que :
container compose up --profile debugdémarre aussi le debugger.
Le scaling est également supporté :
container compose up --scale web=5Le plugin valide les cas où le scaling ne peut pas fonctionner, par exemple lorsque plusieurs replicas tentent de binder le même port statique sur l’hôte.
Les limites de ressources sont supportées via deploy.resources.limits, avec une validation alignée sur le modèle container d’Apple.
Travailler avec Apple container machines
L’écosystème container d’Apple inclut les container machines, et container compose permet d’exécuter un projet dans une machine existante avec --machine.
Par exemple :
container machine create --name devcontainer compose up --machine dev -f compose.yaml -p democontainer compose ps --machine dev -p democontainer compose logs --machine dev -p democontainer compose down --machine dev -p demoLe plugin distingue alors deux contextes d’exécution : l’application sandbox et une container machine.
Cette distinction est importante, car toutes les fonctionnalités ne se comportent pas exactement de la même manière dans les deux contextes. Le plugin explicite ces contraintes au lieu de prétendre que les environnements sont identiques.
Observabilité de l’orchestration locale
Les outils locaux doivent être debuggables.
Quand un démarrage échoue, les développeurs doivent comprendre ce qui s’est passé : quel service a démarré, quelle dépendance a échoué, quelle vague a rollback, quelle opération réseau ou volume a été lancée, et où le temps a été consommé.
container compose émet des événements d’orchestration dans macOS Unified Logging sous :
com.simplifi-ed.container-composeOn peut les inspecter depuis Console.app ou depuis le terminal :
log stream --predicate 'subsystem == "com.simplifi-ed.container-compose" AND category == "orchestration"'Le plugin émet aussi des signposts Instruments pour les chemins critiques du démarrage : parse, plan, création réseau, création volume et vagues d’exécution.
C’est un principe de conception : l’infrastructure locale doit aussi être observable.
Host DNS pour le développement local
Le développement local a souvent besoin de hostnames stables.
Les ports sont utiles, mais les hostnames simplifient les tests navigateur, les callbacks, les cookies et le routage multi-services local.
container compose inclut une fonctionnalité Host DNS opt-in :
services: web: image: nginx:1.27.3 ports: - "8080:80" x-compose: hosts: - web.demo.localPuis :
container compose up --host-dnsmappe le hostname déclaré vers 127.0.0.1 sur l’hôte macOS.
Le plugin reste non privilégié. macOS demande une autorisation uniquement lors de l’écriture dans /etc/hosts, et container compose down supprime le bloc du projet quand c’est possible.
Migration offline d’une stack
Une autre fonctionnalité importante était la possibilité de packager une stack résolue.
container compose save peut regrouper manifest.json, compose.yaml et images.tar dans une archive portable :
container compose save -f compose.yaml -o stack.tarPuis une autre machine peut la charger :
container compose load -i stack.tarcontainer compose up -f compose.yamlCette fonctionnalité ne cherche pas à résoudre tous les problèmes de migration. Elle ne package pas les volumes, l’état des systèmes de fichiers des containers, le push/pull registry ou les secrets. Elle se concentre sur une frontière pratique : configuration Compose résolue et images OCI locales.
C’est suffisant pour beaucoup de workflows offline, de démos, de workshops ou d’environnements contrôlés.
Ce que ce projet n’est pas
Ce projet n’affirme pas qu’Apple Container doit remplacer tous les workflows containers existants aujourd’hui.
Il n’affirme pas non plus que la sémantique Docker Compose peut être copiée parfaitement dans un runtime différent.
Le modèle d’Apple a ses propres contraintes. Certaines sont architecturales. Certaines sont liées à la maturité de l’écosystème. Certaines viennent simplement du fait que nous construisons sur une base nouvelle.
La bonne approche n’est donc pas la compatibilité aveugle.
La bonne approche est une compatibilité pragmatique :
- garder le modèle Compose quand il a du sens
- préserver les commandes familières quand c’est possible
- valider tôt les cas non supportés
- rendre explicite le comportement propre au runtime
- utiliser les capacités natives de macOS au lieu de lutter contre elles
C’est la ligne que nous essayons de tenir.
Les contributions sont ouvertes
Ce projet est open source, et les contributions sont bienvenues.
L’objectif n’est pas de construire un outil interne fermé pour une seule équipe. L’objectif est d’explorer ce que devrait être une orchestration Compose-style au-dessus d’Apple Container, avec des retours réels de développeurs qui essaient de l’utiliser sur de vrais projets.
Les contributions peuvent prendre plusieurs formes : tester le plugin sur des fichiers Compose existants, signaler des fonctionnalités non supportées, améliorer la compatibilité avec des stacks courantes, affiner le comportement spécifique à macOS, améliorer la documentation et les exemples, proposer de meilleurs defaults, contribuer du code Swift ou aider à définir ce que doit devenir un workflow natif proche de Compose sur Apple Container.
Apple Container est encore un écosystème jeune. Le meilleur moment pour façonner l’expérience développeur, c’est maintenant, avant que les patterns ne deviennent des standards accidentels.
Le repository est ouvert :
https://github.com/Simplifi-ED/composeIssues, idées, tests et pull requests sont les bienvenus.
Open source entre l’Europe et l’Afrique
container compose est un projet parmi d’autres dans un effort open source plus large que nous construisons chez Simplifi’ED et Omnivya.
Nous pensons que l’open source ne consiste pas seulement à publier des repositories. Il s’agit de créer des ponts techniques : entre équipes, entre écosystèmes, et entre régions qui résolvent souvent des problèmes d’ingénierie similaires dans des contextes différents.
C’est important pour nous parce que nous travaillons entre l’Europe et l’Afrique.
Les contraintes sont réelles des deux côtés : expérience développeur, coût d’infrastructure, souveraineté, montée en compétence, maturité cloud, sécurité, réglementations locales et besoin de construire des logiciels capables de survivre hors des conditions parfaites de laboratoire.
L’open source nous donne une manière concrète de partager ces apprentissages. Il nous permet de publier des outils, documenter nos décisions, inviter les retours et discuter d’architecture avec des ingénieurs, entreprises, écoles et communautés au-delà d’une frontière commerciale.
Nous avons déjà créé d’autres projets open source, et nous serons heureux d’en parler : ce qui a fonctionné, ce qui a échoué, ce qui doit être amélioré, et où la collaboration a du sens.
Pourquoi c’est important
Le poste de travail développeur est en train de changer à nouveau.
Pendant des années, la réponse par défaut sur macOS consistait à exécuter un moteur container Linux via une couche de virtualisation, puis à construire le workflow développeur au-dessus.
Apple expose maintenant une fondation plus native.
Cela ne remplace pas automatiquement l’écosystème autour des containers. L’écosystème, ce n’est pas seulement l’exécution d’images. C’est l’orchestration, la configuration, les logs, les health checks, les profiles, les volumes, les secrets, le réseau, le DNS local, les workflows offline et la mémoire musculaire des développeurs.
container compose existe parce que la prochaine génération d’outillage container sur macOS a besoin de cette couche.
Nous voulons que les développeurs puissent continuer à écrire :
container compose upet obtenir une vraie stack applicative, pas seulement un container isolé.
État actuel
Le projet est actif et évolue.
Aujourd’hui, il couvre déjà une partie importante de l’orchestration locale Compose-style : commandes de cycle de vie, vagues de dépendances, démarrage basé sur les health checks, nommage de projet, résolution de configuration, profiles, scaling, limites de ressources, logs, exec, stats, watch, save/load, host DNS et support des Apple container machines.
Il reste des limites. Certaines sont documentées. Certaines évolueront avec la maturité de l’écosystème container d’Apple. Certaines demanderont des décisions de conception explicites, car la containerisation native macOS n’a pas exactement la même architecture que Docker Desktop.
C’est précisément pour cela que nous avons commencé maintenant.
Plus cette couche existe tôt, plus les équipes peuvent expérimenter le runtime container d’Apple avec des workflows proches de ceux qu’elles connaissent déjà.
Essayez-le
Installez le plugin via le tap Homebrew Simplifi-ED :
brew tap Simplifi-ED/composebrew trust --formula simplifi-ed/compose/container-composebrew install simplifi-ed/compose/container-composeDémarrez le runtime container d’Apple :
container system startPuis lancez une stack Compose :
container compose up -f compose.yaml -p demoInspectez-la :
container compose ps -p democontainer compose logs -p democontainer compose stats -p demoSupprimez-la :
container compose down -p demoC’est le début d’un workflow de développement container plus natif sur macOS.
Pas en abandonnant l’ergonomie Compose.
En l’apportant à Apple Container, de manière ouverte, avec la communauté.