# How to Build OCI Images Using BuildKit with the container build Command

> Learn to build OCI compliant images on Apple silicon using BuildKit and the container build command. Optimize your workflow with parallel execution and cross-platform support.

- Repository: [Apple/container](https://github.com/apple/container)
- Tags: how-to-guide
- Published: 2026-07-08

---

**The `container build` command leverages a lightweight Linux VM running BuildKit to transform Dockerfiles into OCI-compliant images on Apple silicon, supporting parallel execution, cross-platform builds, and configurable resource limits through the `~/.config/container/config.toml` configuration.**

The `container` CLI is Apple's native tool for creating and running OCI-compatible containers on macOS. When you need to compile a Dockerfile into a runnable image, the `container build` command orchestrates a specialized builder VM that runs the BuildKit engine—the same high-performance build system used by Docker—to produce standards-compliant OCI images optimized for Apple silicon.

## How container build Works

When you invoke `container build`, the CLI does not build images directly on macOS. Instead, it communicates with a dedicated *builder* container that packages BuildKit inside a lightweight Linux VM.

### The Builder VM Architecture

According to [`docs/command-reference.md`](https://github.com/apple/container/blob/main/docs/command-reference.md), the `container build` command parses your CLI flags, prepares the local build context, and forwards the request to the `container-builder-shim` image (default `ghcr.io/apple/container-builder-shim/builder:<tag>`). This shim launches a lightweight VM, mounts your build context, and executes the Dockerfile inside BuildKit. The VM runs as a background service managed by `container builder start` and persists across builds to enable layer caching.

### BuildKit Integration

BuildKit provides the underlying execution engine that implements parallel step processing, intelligent cache sharing, and multi-architecture output. As documented in [`docs/tutorials/start-here.md`](https://github.com/apple/container/blob/main/docs/tutorials/start-here.md), BuildKit runs inside the builder VM and handles all instruction processing, from `RUN` commands to `COPY` operations. The resulting image is automatically stored as a type `oci` image in the local container store.

## Starting the Builder Environment

Before building images, you must start the builder VM with sufficient resources. By default, the builder allocates 2 CPUs and 2 GiB of memory, but large builds require more.

Start the builder with custom resource limits:

```bash
container builder start --cpus 8 --memory 32g

```

You can verify the builder status anytime:

```bash
container builder list

```

To stop the builder and free resources:

```bash
container builder stop

```

## Building Your First OCI Image

With the builder running, create a standard `Dockerfile` in your project directory. The build context (the directory containing the Dockerfile and any files to copy) is specified as the final argument to `container build`.

Create a simple Dockerfile:

```dockerfile
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["python", "app.py"]

```

Build the image with a tag:

```bash
container build --tag myorg/web-app:latest --file Dockerfile .

```

List the resulting OCI image:

```bash
container image list

```

Run a container to verify:

```bash
container run -it myorg/web-app:latest

```

## Advanced container build Options

### Multi-Architecture Builds

BuildKit supports cross-compilation through the `--arch`, `--os`, and `--platform` flags. As specified in [`docs/command-reference.md`](https://github.com/apple/container/blob/main/docs/command-reference.md), you can produce images for multiple architectures in a single invocation by repeating the `--arch` flag.

Build for both Apple silicon and Intel architectures:

```bash
container build \
  --tag myorg/web-app:latest \
  --arch arm64 \
  --arch amd64 \
  --file Dockerfile \
  .

```

### Export Formats and Outputs

By default, `container build` writes OCI images to the local store. However, you can export to other formats using the `--output` flag, which accepts BuildKit-style exporter syntax.

Export as a tarball:

```bash
container build \
  --tag myorg/web-app:latest \
  --output type=tar,dest=./myimage.tar \
  .

```

Other supported export types include `local` (for unpacking to a directory) and `oci` (the default).

### Build Secrets and Caching

BuildKit supports build secrets and cache control. Pass sensitive data without baking it into layers using the `--secret` flag, or bust the cache with `--no-cache`.

Build a specific stage while passing an environment secret:

```bash
container build \
  --target production \
  --no-cache \
  --secret id=MY_API_KEY,env=API_KEY \
  -t myorg/web-app:prod .

```

## Configuring the Builder Environment

Persistent builder settings live in `~/.config/container/config.toml` under the `[build]` section. As documented in [`docs/container-system-config.md`](https://github.com/apple/container/blob/main/docs/container-system-config.md), this file controls the builder image version, resource defaults, and Rosetta translation settings.

Example configuration:

```toml
[build]
cpus = 8
memory = "16g"
rosetta = false
image = "ghcr.io/apple/container-builder-shim/builder:0.12.0"

```

After editing the configuration, restart the builder to apply changes:

```bash
container builder stop
container builder start

```

According to [`docs/how-to.md`](https://github.com/apple/container/blob/main/docs/how-to.md), you can also adjust resources per-invocation with the `--cpus` and `--memory` flags on `container builder start`, making the config file ideal for personal defaults while CLI flags handle one-off adjustments.

## Summary

- The `container build` command requires a running builder VM (`container builder start`) that hosts the BuildKit daemon inside a lightweight Linux VM.
- Build configurations default to 2 CPU/2 GiB but can be customized via CLI flags or the `[build]` section in `~/.config/container/config.toml`.
- BuildKit enables parallel execution, intelligent caching, and multi-architecture builds using `--arch` flags for cross-platform compatibility.
- Output formats are configurable via `--output`, supporting OCI (default), tar archives, and local directory exports.
- The builder image version and Rosetta settings are controlled through the system configuration file, with changes requiring a builder restart to take effect.

## Frequently Asked Questions

### What is BuildKit and why does container use it?

**BuildKit is an advanced build engine developed by Docker** that provides parallel step execution, efficient caching, and multi-platform support. According to the `apple/container` source code, the `container` CLI uses BuildKit because it generates OCI-compliant images efficiently while supporting modern Dockerfile features like multi-stage builds and secrets management. The builder VM runs BuildKit as its core processing engine.

### How do I build images for multiple architectures simultaneously?

**Use repeated `--arch` flags** to specify target architectures in a single build command. For example, `container build --arch arm64 --arch amd64 --tag myapp:latest .` produces a multi-architecture manifest containing both variants. As implemented in [`docs/command-reference.md`](https://github.com/apple/container/blob/main/docs/command-reference.md), BuildKit handles the cross-compilation automatically, leveraging Rosetta on Apple silicon unless explicitly disabled in the configuration file.

### Where is the builder VM configuration stored?

**The configuration lives at `~/.config/container/config.toml`** on your macOS system. The `[build]` section within this file, as documented in [`docs/container-system-config.md`](https://github.com/apple/container/blob/main/docs/container-system-config.md), specifies default CPU counts, memory limits, the builder shim image tag, and Rosetta translation settings. Any changes to this file require restarting the builder with `container builder stop` followed by `container builder start` to take effect.

### How do I export a built image to a tarball instead of the local store?

**Use the `--output` flag with `type=tar`**. The syntax is `container build --output type=tar,dest=./filename.tar -t myimage:latest .`. As noted in [`docs/command-reference.md`](https://github.com/apple/container/blob/main/docs/command-reference.md), this bypasses the local OCI store and writes the image directly to the specified destination, which is useful for sharing images with systems that do not have the `container` CLI installed or for archiving specific build artifacts.