Skip to content

Container Preflight: predict container failures before execution - #1

Merged
raphgm merged 23 commits into
mainfrom
feat/preflight
Sep 24, 2026
Merged

raphgm merged 23 commits into
mainfrom
feat/preflight

Conversation

@raphgm

@raphgm raphgm commented Sep 24, 2026

Copy link
Copy Markdown
Owner

Adds preflight, which predicts Docker and Compose build and start-up failures before anything runs. It checks the project (Compose files, Dockerfiles or a docker run command) against the host and against registry metadata.

What's included

  • preflight: 18 rules covering images and platforms, emulation (QEMU and Rosetta), credential helpers, build context and .dockerignore, BuildKit, Compose versions and variables, memory, disk and GPU, kernel settings, ports, and bind mounts (missing files, permissions, SELinux, Docker Desktop shared folders).
  • Root-cause grouping: checks that depend on an unknown fact are reported once, under that fact's root cause. It also names specific causes for an unreachable daemon: a stale context, a stopped engine, a hung VM, or Docker Desktop running from its installer image.
  • snapshot and preflight --host: predict failures for another machine from a saved profile.
  • learn: turns a real failure into a shareable rule, refined by later failures and by successful runs.
  • bench/: GitHub failure mining with checked precision, plus the labeled development sample and held-out test sample. The eval-frozen tag marks the rules as of the test draw.
  • docs/validation/: checks against real Colima and Docker Desktop on Apple silicon.
  • paper/: draft for the Journal of Systems and Software.
  • CI: fixed; it now reads the Go version from go.mod.

Testing

  • go test ./... passes: unit tests for the parser, host probe, registry, rules, learner and engine.
  • Registry tests against live registries run with PREFLIGHT_LIVE=1.
  • Predictions were checked against real Docker. See docs/validation/2026-09-23-colima-m-series.md.

Preflight parses Compose files and Dockerfiles with Docker's own
parsers, profiles the daemon host (including the Colima VM kernel),
reads image platforms and sizes from registries without pulling, and
predicts build/run failures before anything executes. Checks blocked by
an unknown fact are grouped under that root cause.

Also adds snapshot/--host to predict for another machine, validation
notes from a real Colima run, and fixes the CI Go version.
A VM engine's disk image is a sparse file on the host volume, so the
disk estimate now uses the smaller of VM and host free space, and a new
host.disk rule warns below 10 GiB and errors below 2 GiB. When the
daemon is down on a nearly full disk, the diagnosis says to free space
before starting the VM.
learn runs a command (or reads a log), extracts the decisive error line
as a generalized signature, and records the service and host features
at the time as a rule in .container-doctor/learned.yaml. A repeat
failure drops conditions the runs disagree on; a successful run that
satisfies a rule adds the feature that distinguishes it, or marks the
rule unreliable. Failures a built-in rule already predicts are not
learned twice. Preflight evaluates active learned rules.
mine.py counts GitHub issues per Docker failure category (including
categories preflight does not cover) and samples 30 each; precision.py
checks each sample for the exact error text to estimate precision and
an adjusted count.
A daemon that is starting or starved of memory accepts connections but
never answers, which hung preflight. Probe commands now time out after
20s, and the diagnosis names competing Docker VMs when several run.
Reads the container user from Compose or the image config (via the
registry) and flags bind mounts a non-root container cannot write:
sources Docker will create as root, host directories owned by another
uid, and SELinux hosts without :z/:Z. Skipped where Docker Desktop,
Colima or OrbStack map ownership. Volume permission errors were the
largest uncovered category in the GitHub issue sample.
…unches

On macOS the Desktop VM's command line shows whether amd64 runs under
Rosetta or QEMU and which folders are shared, so mounts.sharing uses the
real shared paths (now an error, matching Docker's 'mounts denied') and
emulation findings know the mechanism. Docker Desktop started from its
mounted installer image is diagnosed as the root cause of a hung daemon.
Validated against Docker Desktop 29.8 on Apple silicon.
- preflight --run checks docker run/create/pull command lines, not only
  Compose projects
- compose.version knows the top-level name key
- mounts.sharing covers Docker Desktop for Linux (home only)
- mounts.permissions flags Postgres data folders bind-mounted from
  Windows, which cannot be chmod-ed
- predicted texts match Docker 29 for missing images and GPU requests
The tool predicts failures before execution; "preflight" says that,
and the new name no longer clashes with the unrelated Docker Doctor.

- Module path github.com/raphgm/container-preflight; binary
  container-preflight.
- `check` is the main command (alias: preflight); the old host health
  checks move to `host`.
- Learned rules live in .container-preflight/learned.yaml.
- Remove the unused report stub; `version` prints the build version,
  set by goreleaser.
- Paper: tool renamed; related work distinguishes Red Hat's preflight
  and kubeadm preflight checks.
The loose check (both words anywhere) reported precision 0.97; requiring
'network <name> not found' or 'declared as external, but could not be
found' gives 0.33 (10/30), cutting the estimate from 17.8k to 6.1k.
Totals, coverage shares and weighted scores in the paper updated.
@raphgm
raphgm merged commit d7e6ba3 into main Sep 24, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant