Apple Container Unboxing & Practice
TL;DR
The Apple Container CLI is a powerful tool for running Linux containers on macOS, especially optimized for Apple Silicon.
The CLI is designed to be developer-friendly, with commands similar to Docker CLI.
For those who are already familiar with Docker CLI, the Container CLI should feel quite familiar, and it provides a more native experience for macOS users.
In this blog post, I will introduce the Container CLI, how to get started with it, and how to use it to run Linux containers on macOS.
About Container CLI
Container is an open source command line tool provided by Apple. It is built for running Linux container on Mac, especially optimized for Apple Silicon. It is wrote in Swift, and built with Containerization Framework . The Apple Containerization and Container CLI are released on WWDC 2025.
If you’re unfamiliar with the Apple Containerization Framework, check out my earlier blog post for an introduction. Since its internal adoption over two years ago, the framework has become widely used within Apple. It was developed by engineers with backgrounds at Docker and the Kata Containers project.
Leveraging the Containerization Framework, running Linux containers on macOS becomes straightforward. Unlike traditional solutions such as Docker Desktop, OrbStack, or Podman-which typically run multiple containers within a single VM — this framework provisions an isolated virtual machine for each container. This approach enhances both security and performance by providing stronger workload separation and minimizing resource contention.
Other than security, I would say the most significant advantage is it provides a native macOS experience for running Linux containers, without the need for a third-party hypervisor or complex setup. This makes it easier for developers to work with Linux containers directly on their macOS machines, at least for Apple Silicon users.
Container CLI should be the first tool to use the Containerization Framework, and it is designed to be a simple CLI with developer-friendly features, docker-like commands.
Getting Started with Container CLI
To get started with native Linux containers solution on macOS, you can use the Container CLI instead of Containerization Framework directly.
One thing to clarify is that the Container CLI relies on the new features and enhancements on macOS 26 beta. You can still use it on macOS 15.5 or later, but they won’t fix the issue found in macOS 15 but not reproduced on macOS 26 beta. So it is recommended to use macOS 26 beta or later for the best experience.
Some limitations on macOS 15 you should be aware in advance:
- Container-to-container communication over the virtual network is not possible.
- The container IP address is not reachable from the host machine.
Here, I will use macOS 15.5 for demonstration.
Install Container CLI
Download the Container CLI from its GitHub release page, the latest version is 0.1.0 as of this writing.
After it installed, you can start the service with command below:
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]:
Installing kernel...
This command will start the container server, and it will also install the default kernel if it is not already installed. The default kernel is a static kernel provided by Kata Containers, which is a lightweight virtual machine solution for running containers.
This is a very important step, or you will get the error below when running any other command:
XPC connection error: Connection invalid
Sub Commands
The Container CLI provides a set of subcommands for managing containers, similar to Docker CLI.
Registry Login
From now on, you can play with the Container CLI. In order to run a container, you need to pull an image first. The Container CLI supports pulling images from Docker Hub and other registries.
Let’s login to Docker Hub first:
container registry login --username <USERNAME> REGISTRY_HOST
You can also set Docker Hub Registry as the default registry:
container registry default set REGISTRY_HOST
Pull an Image
You can pull an image from Docker Hub or other registries using the container images pull
command. The command is similar to the Docker CLI, but it uses the container
prefix and subcommand images pull
, but Docker CLI supports docker pull
and docker images pull
.
# Docker CLI
docker pull nginx:latest
docker images pull nginx:latest
# Container CLI
container images pull nginx:latest
Run a Container
The command to run a container is also similar to the Docker CLI.
# Docker CLI
docker run --rm --name nginx-test nginx:latest
# Container CLI
container run --rm --name nginx-test nginx:latest
Inspect a Container
With inspect
command, you can view the details of a container, including its configuration, networks and status.
# Docker CLI
docker inspect nginx-test
# Container CLI
container inspect nginx-test
List Containers
You can list all running containers with the container ls
command, similar to docker ps
.
# Docker CLI
docker ps
# Container CLI
container ls
Exec into a Container
You can execute commands inside a running container using the exec
command. This is similar to docker exec
.
# Docker CLI
container exec -it nginx-test bash
# Container CLI
container exec -it nginx-test bash
Other Commands
Other container management subcommands are similar to Docker CLI. But the images related operations require the images
subcommand, such as container images ls
, container images rm
, etc. Docker CLI provides more friendly commands like docker rmi
, docker pull
, docker push
, etc.
Here I will not cover all the commands, you can check with container --help
or container <subcommand> --help
to see the detailed usage of each command.
Building Images
Regarding to building images, the Container CLI supports building images using the container build
command, and the Dockerfile syntax is compatible with Docker CLI. You can use the same Dockerfile to build images with Container CLI.
# Docker CLI
docker build -t my-image:latest .
# Container CLI
container build -t my-image:latest .
Network
From the output for container ls
, you can see that each container has its own dedicated IP address, which is a significant improvement over the traditional Docker networking model. This means you don't need to map individual ports for each container, and it provides a more seamless networking experience.
container ls
ID IMAGE OS ARCH STATE ADDR
nginx-test docker.io/library/nginx:latest linux arm64 running 192.168.64.2
Due to the limitations on macOS 15, I won’t try to access the container with its IP address directly, as it won’t work.
DNS
Container includes an embedded DNS server that allows you to resolve container names to their IP addresses.
sudo container system dns create container-dns
container system dns default set container-dns
The first command creates a file under /etc/resolver/
directory, which is used by macOS to resolve DNS queries for the container-dns
domain. The second command sets this DNS as the default for the system.
Then, you can reach the container by its name, such as nginx-test.container-dns
, and it will resolve to the container's IP address.
cat /etc/resolver/containerization.container-dns
domain container-dns
search container-dns
nameserver 127.0.0.1
port 2053
Uninstall Container CLI
To uninstall the Container CLI, you can use the container system stop
command to stop the container service, and then remove the Container CLI binary.
container system stop
git clone https://github.com/apple/container.git
cd container
scripts/uninstall-container.sh -d
-d
option will remove the container data directory, which includes the container images and containers. If you want to keep the data, you can provide -k
option instead, which will keep the data directory and only remove the Container CLI binary for reinstallation later.