How to Build OCI Images Using `container build` with BuildKit
You can build OCI-compliant container images on macOS by using container build, which orchestrates a BuildKit-powered builder VM to execute Dockerfiles and produce multi-architecture outputs.
Apple's container CLI provides native OCI container support for Apple Silicon, leveraging the same high-performance BuildKit engine used by Docker. When you invoke container build, the CLI communicates with the container-builder-shim image to launch a lightweight Linux VM, mount your build context, and execute the Dockerfile instructions. The result is a fully OCI-compliant image stored locally or exported to a tarball.
Architecture Overview
The container build workflow relies on three core components working together to transform Dockerfiles into runnable images.
The container build Command
As documented in docs/command-reference.md, the container build command parses CLI flags, prepares the local build context, and forwards the request to the builder container. It supports standard Dockerfile instructions alongside Apple-specific extensions for multi-architecture output and custom export formats.
Builder VM and Shim
The builder runs inside a lightweight Linux VM launched by container builder start. This VM executes the container-builder-shim image (default ghcr.io/apple/container-builder-shim/builder:<tag>), which contains the BuildKit daemon. Resource limits for this VM—including CPU count, memory allocation, and Rosetta usage—are configurable via the [build] section of ~/.config/container/config.toml, as detailed in docs/container-system-config.md.
BuildKit Integration
BuildKit provides the underlying execution engine, enabling parallel step processing, intelligent cache sharing, and multi-platform output. According to docs/command-reference.md, you can target specific architectures using the --arch, --os, and --platform flags to produce images for multiple architectures (e.g., arm64 and amd64) in a single build invocation.
Starting the Builder
Before building images, you must start the builder VM with sufficient resources for your workload.
# Start with default resources (2 CPU / 2 GiB)
container builder start
# Or allocate specific resources for large builds
container builder start --cpus 8 --memory 32g
The builder persists across builds, maintaining the BuildKit cache for faster incremental builds. To apply configuration changes or free system resources, stop the builder:
container builder stop
Configuring Builder Resources
Persistent builder settings reside in ~/.config/container/config.toml. The [build] section controls the VM resources and the builder image version.
[build]
cpus = 8
memory = "16g"
rosetta = false # Disable Rosetta for native-arm builds
image = "ghcr.io/apple/container-builder-shim/builder:0.12.0"
After modifying this file, restart the builder to apply changes:
container builder stop
container builder start
These configuration options are documented in docs/container-system-config.md and docs/how-to.md.
Building OCI Images
Basic Build Workflow
Create a Dockerfile (or Containerfile) in your project directory, then run:
container build --tag myorg/app:latest .
The CLI automatically pulls the builder shim if absent, launches the VM, and streams build progress to your terminal. The resulting image is stored in the local OCI-compliant image store.
Multi-Architecture Builds
Produce images for multiple architectures simultaneously using the --arch flag:
container build \
--tag myorg/web-app:latest \
--arch arm64 \
--arch amd64 \
--file Dockerfile \
.
This leverages BuildKit's cross-compilation capabilities to generate a multi-platform manifest, as supported by the flags documented in docs/command-reference.md.
Exporting to Tarball
By default, container build writes type oci images to the local store. To export the image as a tarball for sharing or archiving, use the --output flag:
container build \
--tag myorg/web-app:latest \
--output type=tar,dest=./web-app.tar \
.
Advanced Build Options
Multi-Stage and Secret-Aware Builds
BuildKit supports advanced Dockerfile features including multi-stage builds, build secrets, and cache control:
container build \
--target production \
--no-cache \
--secret id=MY_API_KEY,env=API_KEY \
--tag myorg/web-app:prod \
.
This command builds only the production stage, bypasses the cache, and injects the API_KEY environment variable as a build secret without persisting it in the final image layers.
Verifying and Running Images
After building, verify the image exists in the local store:
container image list --quiet
Test the image immediately using container run:
container run -it myorg/web-app:latest
Summary
container buildorchestrates BuildKit inside a lightweight VM to execute Dockerfiles and produce OCI-compliant images.- The builder VM runs the
container-builder-shimimage and is configured via~/.config/container/config.tomlin the[build]section. - Multi-architecture builds use the
--archand--platformflags to target multiple CPU architectures in a single invocation. - Output formats include the default OCI local store or tarball exports via
--output type=tar,dest=.... - Control resource allocation with
container builder start --cpusand--memory, or set defaults in the configuration file.
Frequently Asked Questions
What is the builder shim image?
The builder shim is the container image ghcr.io/apple/container-builder-shim/builder:<tag> that runs inside the builder VM. It contains the BuildKit daemon and supporting tools necessary to execute builds. The specific version is controlled by the image key in the [build] section of your configuration file.
How do I change CPU and memory limits for builds?
You can specify resources temporarily when starting the builder with container builder start --cpus 8 --memory 32g, or permanently by setting cpus and memory values in the [build] section of ~/.config/container/config.toml. Changes to the configuration file require a builder restart to take effect.
Can I build images for Intel Macs from my Apple Silicon Mac?
Yes. Use the --arch amd64 flag (or --arch arm64 --arch amd64 for both) to cross-compile images for x86_64 architectures. BuildKit handles the cross-compilation automatically, and the resulting multi-platform image can run on both Apple Silicon and Intel systems.
How do I export a built image to a Docker-compatible tarball?
Use the --output flag with type tar: container build --output type=tar,dest=./image.tar .. This creates a tarball containing the OCI image layers and manifest, which can be imported into Docker or other container runtimes using standard docker load or similar commands.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →