Reference

Runtime & Environment

This page describes what happens when an Airfield container runs: which container engine is used, how the container is wired to the host, what gets mounted where, and the environment variables that change any of it. The CLI Reference covers commands and file schemas; this page covers behavior.

Container engines

Airfield targets Docker and works with engines that present a Docker-compatible CLI:

If a build fails with invalid mount type "cache", Airfield regenerates the Dockerfile without cache mounts and retries on its own.

Networking and IPC

On Docker, every run, cmd, and shell container starts with --network=host and --ipc=host. This is deliberate: ROS 2 nodes in different containers, and nodes running directly on the host, discover each other over DDS exactly as if they were plain processes on one machine. You do not need to configure discovery servers, port mappings, or a shared Docker network, and tools on the host (ros2 topic echo, rviz2) see topics published from any container.

The trade-off is standard for host networking: containers share the host’s network namespace, so two containers cannot bind the same port.

What gets mounted

Each container receives:

The working directory defaults to the source mount; default_workdir in airfield.yaml overrides it.

Containers created by one image are independent. Two panes running the same package get two containers from the same image, with the same mounts.

The first-run build

Images built for a ROS package carry a small entry script at /opt/airfield-entry.sh. Before running your command, it checks whether the package is already present in the workspace install/ directory:

Because install/ lives on the host, that check sees work done by earlier containers in the same project: the first pane to need a package compiles it, and every later pane finds it built and goes straight to launching.

Two protections make this safe on small boards:

Packages without a ros_distro have no entry script; their commands run in a plain login shell.

GPU access

GPU passthrough depends on the platform:

Dependency manifests can declare host_dependencies (an NVIDIA driver with a minimum version, for example). Airfield evaluates them before the image build: interactive sessions are prompted when a required host dependency is missing, and non-interactive runs (CI) fall back to CPU installs rather than failing.

Teardown

Airfield names each container it starts (airfield-run-<pid>-<id>) and runs it with --rm. When the airfield process receives Ctrl-C, SIGTERM, or SIGHUP (a closed terminal, or tmux kill-session), it stops its own container explicitly instead of trusting the in-container process tree to forward signals. This is why airfield project down leaves no orphaned containers: killing the tmux session signals each pane, and each pane stops its container on the way out.

Processes started under nohup keep their SIGHUP immunity; Airfield does not override it.

After a hard crash (SIGKILL, power loss) where no handler could run, sweep the leftovers:

airfield project down --prune

Environment variables

VariableEffect
AIRFIELD_NO_PULLSkip docker build --pull, so a package can build FROM a locally built base image that exists in no registry (a custom L4T base, for example). Often exported in a plan’s pre_window or a wrapper script.
AIRFIELD_PACKAGES_REPOURL of the shared packages repository. Lets forks, mirrors, and air-gapped sites point at their own manifests. Default: https://github.com/airfield/packages.git.
AIRFIELD_REPOGitHub owner/name slug used by system update and the update check. Set it when running a fork.
AIRFIELD_WORKSPACEHost location of the shared colcon workspace, overriding the default <project>/.airfield/workspace. Point several projects at one path to share a build tree; set it to none to opt out entirely, giving every container a throwaway workspace and removing the lock that serializes concurrent builds.
AIRFIELD_TORCH_INSTALL_TARGETgpu or cpu. Selects GPU passthrough at run time and the wheel flavor for manifests that install PyTorch. TORCH_INSTALL_TARGET is accepted as a fallback name.
AIRFIELD_TORCH_VERSION, AIRFIELD_TORCH_GPU_WHL_TAGVersion and CUDA wheel tag passed to the image build for PyTorch manifests. Airfield sets them itself from a torch==<version> pin and the detected driver; set them manually to override.
AIRFIELD_DEP_<NAME>_VERSIONSet automatically for every exact pin (name==1.2.3) in airfield.yaml, for manifests that read a version at install time.
AIRFIELD_FORCE_DOCKER_CACHE_MOUNTS, AIRFIELD_DISABLE_DOCKER_CACHE_MOUNTSForce BuildKit cache mounts on or off, overriding engine detection. Useful in CI and when troubleshooting builds.
MAKEFLAGS, CMAKE_BUILD_PARALLEL_LEVELOverride the first-run build’s computed compile parallelism.
IN_AIRFIELD_CONTAINERSet to 1 inside every Airfield image. The CLI checks it to refuse container-in-container operations.

Airfield’s own cache and config live under the XDG base directories (~/.cache/airfield, ~/.config/airfield by default) and honor XDG_CACHE_HOME and XDG_CONFIG_HOME.