navigation
TX 002

Apple Container : lancer des conteneurs Linux sur Mac, sans Docker Desktop

Apple Container (containerization) : l'outil natif d'Apple, stable en 1.0 depuis juin 2026, pour créer et exécuter des conteneurs Linux sur macOS 26. Install, build, réseau, volumes, limites — guide pratique.

12 min de lecture

Gravure d'un navire dans les docks de Londres, années 1850

Terminal window
% container run -d --name serveur-web nginx
% container ls
ID IMAGE STATE IP
a3f1c2... nginx:latest running 192.168.64.3
% open http://192.168.64.3

Une ligne pour lancer, une autre pour lister, et on atteint le service directement sur son IP. Pas de daemon Docker permanent, pas d’icône dans la barre des menus, pas de licence à débattre. Depuis 2025, Apple propose container, un outil open source écrit en Swift pour exécuter des conteneurs Linux nativement sur Mac Apple Silicon. La version 1.0 stable est sortie le 9 juin 2026 (la 1.1.0 est déjà là) : la CLI et les API XPC sont désormais figées, avec garantie de compatibilité entre versions correctives.

Cet article est un démarrage pratique complet : installation, build, run, réseau, volumes, ressources, et les limites regardées en face. Si la conteneurisation vous est nouvelle, les notions d’image, de couche et de registre sont les mêmes qu’avec Docker — ce qui suit est directement lisible.

1. Comprendre container et son architecture

container est un outil CLI édité par Apple, open source sur GitHub, sous licence Apache 2.0, gratuit. Il consomme et produit des images compatibles OCI : on pull depuis n’importe quel registry standard (Docker Hub, GitHub Container Registry, registry privé), et on pousse des images que n’importe quel runtime OCI peut rejouer ailleurs (Kubernetes, Docker, Firecracker…).

La stack technique :

  • Swift + le framework Virtualization de macOS pour l’isolation.
  • Le paquet Swift Containerization pour les API bas niveau (images, réseau, démarrage des VM).
  • vminitd, un mini système d’init lui aussi en Swift, qui démarre les conteneurs en une fraction de seconde.

Architecture : une VM par conteneur

C’est la différence fondamentale avec Docker Desktop. Là où Docker fait tourner tous les conteneurs dans une seule VM Linux partagée (un noyau commun), container lance chaque conteneur dans sa propre machine virtuelle légère, via le framework Virtualization de macOS.


Trois conséquences concrètes :

  • Un noyau par conteneur : en théorie, des conteneurs peuvent s’appuyer sur des noyaux différents. L’isolation est plus forte qu’un runtime partagé — un conteneur compromis ne partage pas son noyau avec ses voisins.
  • Une IP par conteneur, exposée sur le réseau de l’hôte macOS (et non enfermée dans un réseau interne de VM comme sous Docker Desktop). On y revient dans la section réseau.
  • Ressources à la demande : CPU et mémoire sont alloués quand un conteneur est actif, libérés ensuite. Pas de VM qui tourne en permanence en arrière-plan.

container ou Docker Desktop : quelles différences ?

Critèrecontainer (Apple)Docker Desktop
ÉditeurAppleDocker, Inc.
LicenceOpen source (Apache 2.0)Propriétaire (gratuit sous conditions, payant en entreprise)
ArchitectureUne micro-VM par conteneurUne VM Linux partagée
Noyau LinuxUn noyau dédié par conteneurNoyau partagé
RéseauUne IP par conteneur (pile macOS)NAT / bridge via la VM
PlateformeApple Silicon + macOS 26 uniquementIntel et Apple Silicon ; macOS, Windows, Linux
DaemonPas de daemon permanentDaemon + icône barre des menus
Docker ComposePas natif (projets tiers)Intégré
DémarrageSous la seconde, ressources à la demandeVM active en permanence
MaturitéStable depuis la 1.0 (juin 2026)Mature, écosystème très large

container n’est donc pas (encore) un remplaçant universel de Docker Desktop. C’est un runtime natif, léger, sans licence, taillé pour Apple Silicon — avec un périmètre plus étroit.

2. Installer container sur macOS

Deux conditions :

  • Mac avec Apple Silicon. Pas de support Intel ; les mainteneurs ne traitent pas les issues non reproductibles sur Apple silicon.
  • macOS 26 (Tahoe). L’outil exploite les nouvelles APIs de virtualisation et réseau de cette version.

Ces deux points excluent les Mac Intel et les macOS antérieurs — c’est la principale barrière à l’adoption. Sur ce créneau précis, c’est en revanche une option crédible.

Installation

Deux méthodes.

Méthode officielle : téléchargez le paquet .pkg signé et notarisé depuis la page des releases. Préférez le paquet signé — il évite de contourner Gatekeeper. Double-clic, mot de passe admin. L’installeur place sous /usr/local/bin : container, container-apiserver, update-container.sh, uninstall-container.sh.

Homebrew (pratique si vous gérez vos outils CLI ainsi) :

Terminal window
brew install container

Démarrer le service et installer le noyau

Une fois installé, on lance le service système qui gère le cycle de vie des conteneurs :

Terminal window
container system start

Au premier lancement, si aucun noyau Linux n’est présent, l’outil propose d’en installer un — issu de Kata Containers :

% container system start
Verifying apiserver is running...
Installing base container filesystem...
No default kernel configured.
Install the recommended default kernel from
https://github.com/kata-containers/kata-containers/releases/download/3.17.0/kata-static-3.17.0-arm64.tar.xz? [Y/n]: y
Installing kernel...

On valide, le service démarre. Pour vérifier que tout est en place :

Terminal window
container system version # versions container + apiserver
container ls -a # liste (vide au premier run)

Note migration : depuis la 1.0, la configuration système passe par un fichier TOML (~/.config/container/config.toml). Les sous-commandes container system property get/set des versions 0.x ont été retirées — à savoir si vous migrez.

Mises à jour et retours arrière via les scripts /usr/local/bin :

Terminal window
container system stop
/usr/local/bin/update-container.sh # montée de version
/usr/local/bin/uninstall-container.sh -k # -k garde les données, -d les supprime
container system start

3. Lancer et piloter vos conteneurs

La syntaxe est volontairement proche de Docker — quasi pas de réapprentissage. Le panneau de commandes :

CONTAINER SUBCOMMANDS: create, run, start, stop, kill, list (ls), delete (rm),
exec, inspect, logs, stats
IMAGE SUBCOMMANDS: build, image (i), registry (r)
SYSTEM SUBCOMMANDS: system (s), builder, volume, machine

Abréviations partout : container ls -a pour container list --all. Lancer un shell interactif, ou un conteneur en arrière-plan :

Terminal window
container run -it alpine sh # shell interactif
container run -d --name serveur-web nginx # détaché, nommé

Suivre les ressources en temps réel — l’équivalent de docker stats :

Terminal window
container stats
CONTAINER ID CPU % MEMORY USAGE NET RX/TX PIDS
serveur-web 0.00% 22.29 MiB / 1.0 GiB 31.49 KiB / 0.59 K 6

Arrêter, inspecter, entrer dans un conteneur :

Terminal window
container stop serveur-web
container inspect serveur-web # détails complets (JSON), dont un bloc resources
container exec serveur-web sh

Travailler avec les images

Pull depuis un registry, avec tag ou architecture explicite :

Terminal window
container image pull alpine
container image pull nginx:1.27-alpine
container image pull --platform linux/amd64 nginx:latest # forcer amd64 sur Apple Silicon
container image pull ghcr.io/<org>/<image>:<tag> # GitHub Container Registry

Lister et inspecter :

Terminal window
container image ls
NAME TAG DIGEST
alpine latest 28bd5fe8b56d
nginx latest ec4ed8b5299e
container image inspect nginx:latest # métadonnées détaillées (JSON)

Sur Apple Silicon, c’est la variante arm64 qui est récupérée par défaut.

Limite à connaître : il n’existe pas d’équivalent à docker search. Aucune commande pour interroger Docker Hub depuis le terminal. Pour trouver une image, passez par hub.docker.com ou un client graphique.

4. Construire et publier une image OCI

On build une image personnalisée : une page statique servie par Nginx.

Terminal window
mkdir mon-app && cd mon-app
FROM nginx:alpine
LABEL org.opencontainers.image.title="mon-app" \
org.opencontainers.image.description="Démo servie par Nginx"
COPY index.html /usr/share/nginx/html/index.html
EXPOSE 80

Un index.html minimal à côté, puis le build :

Terminal window
container build -t mon-app .

Le piège Rosetta 2

À ce build, vous pouvez tomber sur cette erreur :

Error: internalError: "failed to bootstrap container"
(cause: ... "Rosetta is not installed" ...)

Le builder BuildKit s’appuie sur Rosetta 2 (la couche de traduction x86→ARM d’Apple). Si elle n’est pas installée, une commande suffit :

Terminal window
softwareupdate --install-rosetta --agree-to-license
container build -t mon-app . # relance → succès

Build multi-architecture et push

container sait produire des images multi-arch (ARM64 + AMD64), pratique pour publier une image consommable partout :

Terminal window
container build --arch amd64,arm64 -t mon-app:1.0.0 .

Publication sur un registry — privilégiez un jeton d’accès personnel (PAT) plutôt qu’un mot de passe, avec date d’expiration :

Terminal window
container registry login --username <user> docker.io
container image tag mon-app:latest docker.io/<user>/mon-app:1.0.0
container image push docker.io/<user>/mon-app:1.0.0
container registry list # registres où des identifiants sont enregistrés

L’image construite ici tourne ensuite sur n’importe quel runtime OCI. C’est le vrai gain par rapport à un runtime fermé : pas de format propriétaire, pas de lock-in.

5. Réseau : exposer et nommer un conteneur

C’est ici que le modèle se démarque vraiment. Sous Docker Desktop, les adresses IP des conteneurs vivent dans un réseau interne à la VM et ne sont pas joignables depuis macOS : on publie un port (-p 8080:80) pour atteindre le service via localhost. Avec container, chaque conteneur reçoit une IP exposée sur le réseau de l’hôte macOS, directement joignable, sans publication de port :

Terminal window
container ls # serveur-web running 192.168.64.3
open http://192.168.64.3

Joindre un conteneur par son nom

On peut aussi résoudre un conteneur par <nom>.<domaine> plutôt que par son IP. Mais ça demande deux étapes complémentaires qui ne font pas la même chose :

  1. Enregistrer le domaine auprès de macOS (nécessite sudo) — c’est lui qui rend le domaine résolvable depuis l’hôte :

    Terminal window
    sudo container system dns create mac
  2. Désigner ce domaine comme défaut dans ~/.config/container/config.toml — ce fichier utilisateur ne fait que choisir le domaine à appliquer ; il ne peut pas faire l’enregistrement système :

    [dns]
    domain = "mac"

Les deux sont requis. Déclarer un domaine dans config.toml sans l’avoir créé à l’étape 1 pointe vers un domaine que macOS ne sait pas router. Le service ne relit ce fichier qu’au démarrage :

Terminal window
container system stop && container system start
container system dns list # DOMAIN: mac

Dès lors, serveur-web.mac se résout depuis le Mac.

6. Persister les données (volumes, bind mounts)

Par défaut, tout ce qu’un conteneur écrit disparaît avec lui. Pour conserver un état, deux mécanismes — comme Docker.

Bind mount (idéalement en dev : éditer le code côté Mac, l’exécuter dans le conteneur) :

Terminal window
container run -it -v $(pwd):/app -w /app alpine sh
container run -it -v $(pwd)/data:/data,readonly alpine sh # lecture seule

Volume nommé (état applicatif géré par container, indépendant de l’arborescence hôte — recommandé pour une base) :

Terminal window
container volume create donnees-bdd
container run -d --name bdd \
-e POSTGRES_PASSWORD=secret \
-v donnees-bdd:/var/lib/postgresql/data \
postgres:16
container volume ls
container volume inspect donnees-bdd
container volume prune # supprime les volumes non utilisés

Un volume utilisé par un conteneur, même arrêté, ne peut pas être supprimé : retirez d’abord le conteneur qui le référence.

CritèreBind mount -v /chemin:/cibleVolume nommé -v nom:/cible
EmplacementUn dossier précis du MacGéré par container
Cas typeDev : éditer le code côté MacDonnées applicatives (BDD, journaux)
Accès FinderOuiNon, via le conteneur
PortabilitéDépend de l’arborescence hôteIndépendant du poste

En pratique : bind mount pour le code que vous éditez, volume nommé pour l’état que l’application produit.

7. Dimensionner CPU et mémoire

Par défaut, un conteneur reçoit 4 CPU et 1 Go de RAM. Pour ajuster :

Terminal window
container run -d --name web --cpus 2 --memory 2g nginx
  • --cpus <n> : cœurs alloués à la VM du conteneur.
  • --memory <taille> : suffixes k/m/g/t, unités binaires (2g = 2 Gio) ; sans suffixe, en octets.

Vérifiable via container inspect (bloc resources). Cas particulier du builder : la VM BuildKit a ses propres valeurs par défaut, plus modestes (2 CPU, 2 Gio). Pour un build lourd, démarrez-la explicitement :

Terminal window
container builder start --cpus 8 --memory 8g

Plutôt que de répéter --cpus/--memory à chaque run, on peut définir des valeurs par défaut persistantes dans ~/.config/container/config.toml :

[container]
cpus = 2
memory = "2g"

8. Aller plus loin : machine, Compose, GUI

container machine : un Linux persistant façon WSL

La 1.0 introduit aussi le mode container machine, qui fournit un environnement Linux persistant sur le Mac. Là où un conteneur est calqué sur une application éphémère, une container machine est calquée sur un système Linux complet : votre dossier personnel macOS y est monté, vous éditez côté Mac et compilez côté Linux, et vous pouvez y faire tourner des services au long cours. C’est l’équivalent le plus proche de WSL côté macOS. C’est un sujet à part entière, qui mérite son propre article.

Écosystème : Compose et interfaces graphiques

Docker Compose n’est pas supporté nativement. Décrire une stack multi-services dans un docker-compose.yml et la lancer d’une commande n’est pas (encore) possible avec container seul. La communauté commence à combler ce vide — par exemple Container-Compose (de Mcrich23, en Swift), qui lit un fichier au format Compose et le traduit en commandes container. Pratique mais encore immature.

Côté interfaces graphiques (Apple ne fournit rien d’officiel), quelques clients open source s’appuient sur la CLI ou les API :

  • Orchard : app macOS native en Swift, via XPC. Création/démarrage/arrêt de conteneurs, pull et recherche d’images, logs parallèles, monitoring CPU/mémoire/réseau.
  • iContainer : app SwiftUI (MIT), tableau de bord, shell interactif persistant, stats graphées, gestion des images et registres.

9. Verdict : container ou Docker Desktop ?

Limites honnêtes

  • Apple Silicon + macOS 26 uniquement. C’est l’API de virtualisation qui dicte. Flotte Intel ou macOS antérieur → Docker Desktop ou Colima.
  • Pas de Docker Compose natif. Pour une stack web + db + cache, l’ergonomie Compose reste imbattable ; on se rabat sur des projets tiers immatures.
  • Pas de runtime partagé. Le modèle micro-VM implique un noyau par conteneur. Sur de la densité forte, la RAM grimpe plus vite qu’avec Docker. À benchmarker au-delà de quelques conteneurs.
  • Pas de docker search. Recherche d’images via le site Docker Hub ou un client graphique.
  • Écosystème jeune. Moins d’intégrations, moins de recettes que Docker installé depuis quinze ans.

À retenir

container apporte une chose que Docker Desktop n’a jamais offerte : un runtime OCI natif, signé, open source, sans licence — sous la condition stricte d’Apple Silicon + macOS 26. Le modèle « une VM par conteneur » donne une isolation forte par défaut et des ressources à la demande, au prix d’une densité plus gourmande. La portabilité OCI est réelle : ce que vous buildez ici tourne ailleurs. Avec la 1.0 stable (juin 2026) et la fonctionnalité container machine, l’outil devient crédible pour du dev quotidien sur un Mac récent. Pour une flotte mixte, du Compose ou de la densité, Docker Desktop reste.

Sources : dépôt apple/container, paquet apple/containerization, session WWDC25 « Meet Containerization », article IT-Connect de référence.

Table des matières

My avatar

Merci d’avoir lu cet article ! N’hésitez pas à consulter mes autres publications ou à me contacter via les liens sociaux en bas de page.

Commentaires