A very first test with Apple containers!
Introduction
In the world of software development, few concepts have been as transformative as containerization. For years, developers have battled the infamous “works on my machine” problem — a frustrating situation where code functions perfectly in one environment but fails to run in another. Containers emerged as the ultimate solution, providing a consistent, isolated, and portable environment that bundles an application and all its dependencies, ensuring it runs the same way everywhere.
Traditionally, developers on macOS have relied on virtualization technologies to run containers, primarily through tools like Docker Desktop. While effective, this layer of virtualization often introduced performance overhead and a slight disconnect from the native operating system. However, a new chapter is beginning. With the introduction of native container support on macOS, Apple is bringing containerization directly into the core of its operating system. This is poised to dramatically improve performance, streamline developer workflows, and usher in a new era of seamless, efficient development. This shift holds significant implications for how we build, test, and deploy applications on Apple’s platform.
By the way, since Docker Desktop is a commercial software, I use Podman / Podman desktop, open-source tool(s) which in many regards is way better than Docker Desktop.
First tests
If you want to try Apple “container”, go to the GitHub page (link provided below) and follow the steps.
Below is what we can read from the public Apple’s GitHub page;
container is a tool that you can use to create and run Linux containers as lightweight virtual machines on your Mac. It's written in Swift, and optimized for Apple silicon.
The tool consumes and produces OCI-compatible container images, so you can pull and run images from any standard container registry. You can push images that you build to those registries as well, and run the images in any other OCI-compatible application.
container uses the Containerization Swift package for low level container, image, and process management.
The very first step to do is to download the container package and install it on a your Mac computer (silicon only). The releases are avaiable from this page: https://github.com/apple/container/releases
Once the package is installed, run the following command and follow the steps ⬇️
> container system start
Verifying apiserver is running...
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...
> container system start
Verifying apiserver is running...
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...
> container system start
Verifying apiserver is running...
Then, refering to the documentation, you need to “Configure memory and CPUs for your containers”.
Since the
containers
created by container are lightweight virtual machines, consider the needs of your containerized application when you usecontainer run
. The--memory
and--cpus
options allow you to override the default memory and CPU limits for the virtual machine. The default values are 1 gigabyte of RAM and 4 CPUs. You can use abbreviations for memory units; for example, to run a container for imagebig
with 8 CPUs and 32 gigabytes of memory, use:
container builder start --cpus 8 --memory 32g
After this point, I followed the steps from this point on: “Build an image https://github.com/apple/container/blob/main/docs/tutorial.md#build-an-image”.
mkdir web-test
cd web-test
FROM docker.io/python:alpine
WORKDIR /content
RUN apk add curl
RUN echo '<!DOCTYPE html><html><head><title>Hello</title></head><body><h1>Hello, world!</h1></body></html>' > index.html
CMD ["python3", "-m", "http.server", "80", "--bind", "0.0.0.0"]
container build --tag web-test --file Dockerfile .
But after failing 3 times (and not being able to resolve the problem);
> container build --tag web-test --file Dockerfile .
[+] Building 11.9s (5/8)
=> [resolver] fetching image...docker.io/library/python:alpine 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> oci-layout://docker.io/library/python:alpine@sha256:9ba6d8cbebf0fb6546ae71f2a1c14f6ffd2fdab83af7fa5669734ef30ad48844 0.0s
=> => resolve docker.io/library/python:alpine@sha256:9ba6d8cbebf0fb6546ae71f2a1c14f6ffd2fdab83af7fa5669734ef30ad48844 0.0s
=> CACHED [linux/arm64/v8 1/6] WORKDIR /content 0.0s
=> ERROR [linux/arm64 2/6] RUN apk update 10.1s
------
> [linux/arm64 2/6] RUN apk update:
0.056 fetch https://dl-cdn.alpinelinux.org/alpine/v3.22/main/aarch64/APKINDEX.tar.gz
5.071 WARNING: updating and opening https://dl-cdn.alpinelinux.org/alpine/v3.22/main: temporary error (try again later)
5.071 fetch https://dl-cdn.alpinelinux.org/alpine/v3.22/community/aarch64/APKINDEX.tar.gz
10.09 WARNING: updating and opening https://dl-cdn.alpinelinux.org/alpine/v3.22/community: temporary error (try again later)
10.09 4 unavailable, 0 stale; 29 distinct packages available
------
Error: unknown (2): failed to solve: process "/bin/sh -c apk update" did not complete successfully: exit code: 4
I decided to bypass this and made a vey basic test as follows… ⬇️
- The new Dockerfile;
FROM docker.io/python:alpine
WORKDIR /content
COPY index.html .
EXPOSE 80
CMD ["python3", "-m", "http.server", "80", "--bind", "0.0.0.0"]
- A simple HTML file;
<!DOCTYPE html>
<html>
<head>
<title>Hello</title>
</head>
<body>
<h1>Hello, world!</h1>
</body>
</html>
- Build & Run ⬇️
container build --tag web-test --file Dockerfile .
[+] Building 1.2s (7/7) FINISHED
=> [resolver] fetching image...docker.io/library/python:alpine 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> oci-layout://docker.io/library/python:alpine@sha256:9ba6d8cbebf0fb6546ae71f2a1c14f6ffd2fdab83af7fa5669734ef30ad48844 0.0s
=> => resolve docker.io/library/python:alpine@sha256:9ba6d8cbebf0fb6546ae71f2a1c14f6ffd2fdab83af7fa5669734ef30ad48844 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 140B 0.0s
=> CACHED [linux/arm64/v8 1/3] WORKDIR /content 0.0s
=> [linux/arm64/v8 2/3] COPY index.html . 0.0s
=> exporting to oci image format 0.1s
=> => exporting layers 0.0s
=> => exporting manifest sha256:d8250bf6d460293ddd6c726a6c6d2fedf5572cc72016ecfef6b9391c7bbcd850 0.0s
=> => exporting config sha256:d3f2c260639da2faf5d3f965dc8683105c15142f10b9290977bd5d3e796b43d6 0.0s
=> => exporting manifest list sha256:7d964d2accb3140ccfb8ba01248c2aedc8a713f0e678a8bd7b82dd343462fc0b 0.0s
=> => sending tarball 0.1s
Successfully built web-test:latest
container run -p 8080:80 --rm web-test
192.168.64.1 - - [08/Sep/2025 07:05:46] "GET / HTTP/1.1" 200 -
192.168.64.1 - - [08/Sep/2025 07:05:46] code 404, message File not found
192.168.64.1 - - [08/Sep/2025 07:05:46] "GET /favicon.ico HTTP/1.1" 404 -
- You can also test from the command line;
> curl http://localhost:8080
curl: (52) Empty reply from server
> container list
ID IMAGE OS ARCH STATE ADDR
buildkit ghcr.io/apple/container-builder-shim/builder:0.6.0 linux arm64 running 192.168.64.2
98e2f6ae-ae92-4ca9-8ffd-0dd7b61abba3 web-test:latest linux arm64 running 192.168.64.4
Success ⛳
- Stop the container.
> container stop web-test
- Delete the container.
> container image list
NAME TAG DIGEST
python alpine 9ba6d8cbebf0fb6546ae71f2...
web-test latest 7d964d2accb3140ccfb8ba01...
> container images delete web-test
web-test:latest
Reclaimed 124,7 MB in disk space
Conclusion
We’ve seen how the introduction of native support has made using containers on macOS a seamless experience. This is a true game-changer, not just for performance, but also for paving the way for open-source container building and deployment tools. This integration lowers the barrier to entry, making it easier for developers to embrace powerful, community-driven solutions like Podman, which in turn fosters a more open and collaborative container ecosystem. This is a significant step forward, and it’s exciting to think about what the future holds.
Links
- Apple Container: https://github.com/apple/container
- Package Installation: https://github.com/apple/container/releases
Top comments (0)