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
@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.
Create an artifact for the package.
Opts:
make_args: - Extra arguments to be passed to make.
@spec system_shell(Nerves.Package.t()) :: :ok
Connect to a system configuration shell in a container