Nerves.Artifact.BuildRunners.Container (nerves v1.15.0)

Copy Markdown View Source

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.

Summary

Functions

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.

Create an artifact for the package.

Connect to a system configuration shell in a container

Functions

available?()

@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(pkg, toolchain, opts)

Create an artifact for the package.

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

system_shell(pkg)

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

Connect to a system configuration shell in a container