# `Nerves.Artifact.BuildRunners.Container`
[🔗](https://github.com/nerves-project/nerves/blob/v1.15.1/lib/nerves/artifact/build_runners/container.ex#L5)

Produce a Nerves artifact using Apple's `container` CLI (github.com/apple/container).

This is a port of `Nerves.Artifact.BuildRunners.Docker` that runs the build in
a lightweight Linux VM managed by Apple's container tooling instead of Docker.
Requires Apple Silicon and container CLI >= 1.0.0. Only supports
`nerves_system_br` >= 1.28.0 (image runs as user `nerves`, working dir
`/home/nerves/project`).

For `type: :system` packages, Nerves selects this runner automatically on
Apple Silicon Macs that have the `container` CLI installed (see `available?/0`);
every other host keeps the stock selection (`Docker` on macOS without the CLI
or on Intel, `Local` on Linux). Setting `build_runner:` in the package config
still takes precedence.

## Images

By default the official `ghcr.io/nerves-project/<platform>:<version>` image is
pulled (multi-arch; runs natively as arm64 on Apple Silicon). A custom image
can be configured like with the Docker build runner:

    build_runner_config: [
      container: {"Containerfile", "my_system:0.1.0"}
    ]

An existing `docker: {...}` key (for the stock Docker build runner) is
honored as a fallback, so cross-platform systems don't need to declare the
same image twice; `container:` takes precedence when both are set.

## Resources

Every `container run` boots its own VM whose defaults (4 CPUs / 1 GB RAM) are
far too small for Buildroot. This runner therefore allocates all host cores
and half the host RAM (minimum 8G) by default. Override via
`build_runner_config` or environment variables:

    build_runner_config: [
      cpus: 8,
      memory: "24G",     # or :host to allocate all host RAM (e.g. WebKit builds)
      volume_size: "256G"
    ]

Environment variables `NERVES_CONTAINER_CPUS`, `NERVES_CONTAINER_MEMORY` and
`NERVES_CONTAINER_VOLUME_SIZE` take precedence over the config. The memory
ceiling is cheap: Virtualization.framework only faults pages in as the VM
actually uses them.

## Volumes and cache

Like the Docker build runner, the build directory lives in a named volume
(`<app>-<id>`, id stored at `ARTIFACT_DIR/.container_id`). Volumes are sparse
EXT4 images — fast and case-sensitive, unlike virtiofs bind mounts. The host
`NERVES_DL_DIR` is bind-mounted at `/nerves/dl` for the download cache and to
copy the finished artifact back to the host.

Unlike the Docker build runner, `nerves_system_br` is NOT bind-mounted at
`/nerves/env/platform` directly: `create-build.sh` extracts the Buildroot
tarball (full of symlinks) there, and GNU tar cannot create symlinks through
apple/container's virtiofs (apple/container#1209). Instead a second named
volume (`<app>-<id>-platform`) is mounted there, the host sources are
bind-mounted read-only at `/nerves/env/platform-src`, and the runner rsyncs
them into the volume before each build (preserving the extracted
`buildroot*` tree).

Fresh volumes are owned by root, so the runner chowns the build directory and
platform directory to the image's `nerves` user before each build.

# `available?`

```elixir
@spec available?() :: boolean()
```

Whether this host can build with Apple containers: an Apple Silicon Mac with
the `container` CLI installed. `Nerves.Artifact.build_runner/1` uses this to
auto-select the runner for `type: :system` packages.

# `build`

Create an artifact for the package.

Opts:
  `make_args:` - Extra arguments to be passed to make.

# `system_shell`

```elixir
@spec system_shell(Nerves.Package.t()) :: :ok
```

Connect to a system configuration shell in a container

---

*Consult [api-reference.md](api-reference.md) for complete listing*
