Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
26d3455
feat: add preflight, joint project/host failure prediction
raphgm Sep 23, 2026
d2ef1bf
feat(preflight): detect low host disk for VM-based Docker engines
raphgm Sep 23, 2026
39f0d2c
feat: learn preflight rules from real failures
raphgm Sep 23, 2026
74962e9
bench: mine and verify GitHub issues per failure category
raphgm Sep 23, 2026
9491cb4
fix(preflight): time out probe commands and diagnose hung daemons
raphgm Sep 24, 2026
70a977c
feat(preflight): predict bind-mount permission failures
raphgm Sep 24, 2026
9a6be8d
feat(preflight): read Docker Desktop's VM; diagnose installer-disk la…
raphgm Sep 24, 2026
2ebcb6c
bench: stratified sample of 124 issues with first-rater labels
raphgm Sep 24, 2026
b8673da
bench: record the 40-issue second-rater subset
raphgm Sep 24, 2026
ac7463b
feat(preflight): rules for misses found in the labeled sample
raphgm Sep 24, 2026
e014f3c
bench: re-score labels after rules for sampled misses
raphgm Sep 24, 2026
d8a6629
bench: held-out test sample (121 issues) labeled against frozen rules
raphgm Sep 24, 2026
81082d3
bench: second rater labels 40 issues from the held-out test sample
raphgm Sep 24, 2026
f8fb13c
paper: first draft for the Journal of Systems and Software
raphgm Sep 24, 2026
db86707
paper: fix affiliation placeholder so the draft compiles
raphgm Sep 24, 2026
49846ae
paper: compile with Tectonic; plain affiliation placeholder
raphgm Sep 24, 2026
a3609c1
paper: architecture figure and generated category table
raphgm Sep 24, 2026
b28d9ce
paper: author affiliation
raphgm Sep 24, 2026
10ad4cf
Rename to Container Preflight
raphgm Sep 24, 2026
33ab084
docs: record host-disk-pressure incident that made Docker Desktop rea…
raphgm Sep 24, 2026
eaa89b0
docs: design sketch for a Kubernetes version; paper future work
raphgm Sep 24, 2026
e0e90aa
bench+paper: verify 'network not found' with Docker's exact phrasing
raphgm Sep 24, 2026
87ba461
Add citation metadata for Zenodo archiving
raphgm Sep 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.22'
go-version-file: go.mod

- name: Verify dependencies
run: go mod verify
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,6 @@ go.work.sum

# env file
.env
paper/*.pdf
paper/*.log
paper/*.aux
4 changes: 3 additions & 1 deletion .goreleaser.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
version: 2
project_name: container-doctor
project_name: container-preflight
before:
hooks:
- go mod tidy
Expand All @@ -16,6 +16,8 @@ builds:
ignore:
- goos: windows
goarch: arm64
ldflags:
- -s -w -X github.com/raphgm/container-preflight/cmd.Version={{.Version}}
archives:
- format: tar.gz
# this name template makes the OS and Arch compatible with the results of uname.
Expand Down
8 changes: 8 additions & 0 deletions .zenodo.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"title": "Container Preflight: predicting container deployment failures before execution (software and evaluation data)",
"upload_type": "software",
"description": "Container Preflight predicts Docker and Docker Compose build and start-up failures before execution by jointly analyzing project artifacts, the host environment and registry metadata. This archive contains the tool, its rules, the GitHub failure-mining scripts and data, the labeled development and held-out test samples, and the field-validation notes used in the accompanying paper.",
"creators": [{"name": "Gab-Momoh, Raphael", "affiliation": "Paynautik Limited"}],
"license": "MIT",
"keywords": ["containers", "Docker", "Docker Compose", "configuration errors", "failure prediction", "root cause analysis"]
}
11 changes: 11 additions & 0 deletions CITATION.cff
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
cff-version: 1.2.0
message: "If you use this software or its data, please cite it as below."
title: "Container Preflight: predicting container deployment failures before execution"
type: software
authors:
- family-names: Gab-Momoh
given-names: Raphael
affiliation: Paynautik Limited
repository-code: "https://github.com/raphgm/container-preflight"
license: MIT
keywords: [containers, Docker, Docker Compose, configuration errors, failure prediction, root cause analysis]
127 changes: 114 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,109 @@
# Container Doctor 🩺
# Container Preflight ✈️

`container-doctor` is a fast, extensible CLI tool designed to diagnose your system's readiness for running Docker and container workloads. It performs health checks across your system, Docker daemon, and Compose installation, alerting you to critical issues like low memory, insufficient disk space, or missing dependencies.
**Predict container failures before you run, and diagnose them at the root cause when they happen.**

## Features
`container-preflight` predicts whether a container project will build and run on a machine **before you run it**, and explains each predicted failure once, at its root cause.

Linters look only at your Dockerfile. `docker info` looks only at your machine. Most "works on my machine" failures come from the mismatch between the two: an amd64-only image on an Apple silicon laptop, a Compose file that needs more memory than Docker Desktop's VM has, a `COPY` of a file your `.dockerignore` excludes, a port something else already holds. `container-preflight check` checks the project and the host together.

## Check a project

```bash
container-preflight check .
```

Preflight builds three views and joins them:

1. **What the project needs.** The Compose file and every Dockerfile are parsed with Docker's own parsers (`compose-go`, BuildKit's Dockerfile frontend). This covers platforms, memory limits and replicas, published ports, bind mounts, `COPY` sources (only in stages BuildKit will actually build), BuildKit-only syntax, Compose features and interpolated variables.
2. **What the host offers.** The daemon's platform and memory (on macOS and Windows these are the VM's, not the laptop's), emulation, Compose/buildx versions, kernel settings, local images, credential helpers and live port usage.
3. **What registries publish.** Each image's platforms and download size, read from the registry without pulling.

Each finding quotes its evidence from both sides and the error Docker would print:

```
✗ [web] COPY source ".env.production" is excluded by .dockerignore Dockerfile:11
web/.dockerignore: pattern ".env*"
would fail with: "failed to compute cache key: \"/.env.production\": not found"
fix: Remove or negate the pattern ".env*" in web/.dockerignore.
```

### Root causes, not symptom lists

Checks depend on facts: the Docker CLI → the daemon → its platform and memory, and so on. When a fact cannot be established, every check that needs it is grouped under that single root cause instead of failing separately. Checks that do not depend on it keep running.

```
ROOT CAUSES
✗ Docker daemon is not reachable
fix: Start Docker Desktop (or `colima start`, `sudo systemctl start docker`) …
blocks 5 check(s): image.platform, resources.memory, resources.gpu, …
```

### Predict for another machine

```bash
# on the target machine (a teammate's laptop, a CI runner, a server)
container-preflight snapshot -o ci-runner.json

# anywhere
container-preflight check . --host ci-runner.json
```

`examples/` contains a deliberately broken project and two example host snapshots. The same project gets different predictions on each:

```bash
container-preflight check examples/broken-shop --host examples/hosts/macbook-m2-desktop.json
container-preflight check examples/broken-shop --host examples/hosts/ubuntu-legacy-server.json
```

### Learning from real failures

Built-in rules cover common failures. `learn` turns the failures your project actually hits into new rules:

```bash
container-preflight learn -- docker compose up db
```

It runs the command and extracts the decisive error line from the output. It turns that line into a signature, with addresses, IDs, paths and numbers generalized. It then records the conditions at the time: image, platform, emulation (QEMU/Rosetta), memory, builder, and which environment variables were set (never their values). The rule goes to `.container-preflight/learned.yaml`; commit it, and preflight predicts the failure for everyone on the team.

Rules improve with evidence:

- **Another failure with the same error** drops the conditions the two runs disagree on, which makes the rule more general.
- **A working run** (`learn --success -- docker compose up -d`) that satisfies a rule adds the condition that tells it apart from the failures, which makes the rule more specific. If no such condition exists, the rule is marked unreliable and no longer reported.
- **A failure a built-in rule already predicted** is reported as such and is not learned twice.

Example from a real run: Postgres started without a password failed. `learn` created a rule for `image=postgres`. After a password was added, the successful run refined the rule to `env.POSTGRES_PASSWORD=unset`, and preflight now flags any Compose file that uses Postgres without one.

### Rules

| Rule | Predicts |
|---|---|
| `image.exists` | tag or repository missing from the registry |
| `image.platform` | no variant for the host's platform, emulation needed or unavailable (`exec format error`) |
| `registry.credentials` | configured credential helper not installed (`error getting credentials`) |
| `build.context` | `COPY`/`ADD` sources missing, excluded by `.dockerignore`, or outside the context; bad target or ARG |
| `build.buildkit` | `RUN --mount`, heredocs, `COPY --chmod/--link` without BuildKit |
| `compose.version` | Compose features newer than the installed Compose (`include`, `name`, `develop`, hooks, `gpus`, `models`) |
| `compose.env` | unset variables, required `${VAR:?}` without a value |
| `resources.memory` | known image minimums and total limits vs Docker's memory |
| `resources.disk` | image download size ×2.5 vs free disk (the smaller of the VM disk and the host volume it lives on) |
| `host.disk` | too little space on this machine for Docker Desktop/Colima/OrbStack to start or grow their VM |
| `resources.gpu` | GPU requests without the NVIDIA runtime, or on macOS |
| `kernel.sysctl` | `vm.max_map_count` for Elasticsearch/OpenSearch/SonarQube |
| `ports.conflict` | two services, or several replicas, on one host port |
| `ports.host` | host port already held by another process or container; privileged ports under rootless Docker |
| `mounts.bind` | missing bind sources that Docker will turn into directories, stale empty directories |
| `mounts.permissions` | non-root containers writing to bind mounts Docker creates as root or that another uid owns; SELinux without `:z`; Postgres data folders bind-mounted from Windows |
| `mounts.sharing` | paths outside Docker Desktop's shared folders (read from the running VM on macOS; home only on Linux) |

Containers started without Compose are checked the same way:

```bash
container-preflight check --run "docker run -p 8080:80 -v ./site:/usr/share/nginx/html nginx:1.27"
```

Use `--format json` for machine-readable output and `--offline` to skip registry lookups. The exit code is 1 when a blocking problem is predicted.

## Other commands

- **System Diagnostics**: Checks your operating system, CPU architecture, memory (RAM), and disk space to ensure you meet minimum requirements.
- **Docker Health**: Validates that Docker is installed, the daemon is running, the socket is accessible, and client/server versions are compatible.
Expand All @@ -17,46 +118,46 @@
### Using Go
If you have Go installed, you can install the CLI directly:
```bash
go install github.com/raphgm/container-doctor@latest
go install github.com/raphgm/container-preflight@latest
```

### From Releases
Pre-compiled binaries for **macOS**, **Linux**, and **Windows** are automatically generated for every release.
Head over to the [Releases page](https://github.com/raphgm/container-doctor/releases) to download the binary for your operating system.
Head over to the [Releases page](https://github.com/raphgm/container-preflight/releases) to download the binary for your operating system.

---

## Usage

### 1. Run Health Checks
### Host health checks
Run the diagnostic engine to check your environment:
```bash
container-doctor check
container-preflight host
```

You can export the results to different formats using the `--format` flag:
```bash
# JSON Output
container-doctor check --format json > report.json
container-preflight host --format json > report.json

# Markdown Output
container-doctor check --format markdown > report.md
container-preflight host --format markdown > report.md

# HTML Output (Standalone Webpage)
container-doctor check --format html > report.html
container-preflight host --format html > report.html
```

### 2. Inspect a Project
### Inspect a project
Statically analyze the configuration files in your current directory (or any specified path):
```bash
container-doctor inspect .
container-preflight inspect .
```

---

## Architecture & Extensibility

`container-doctor` is built with a highly decoupled, plugin-based architecture.
`container-preflight` is built with a highly decoupled, plugin-based architecture.

- **Engine**: The core `internal/engine` runs the execution loop and aggregates results.
- **Providers**: Checks are grouped by Providers (e.g., `system`, `docker`, `compose`).
Expand Down
Binary file added bench/__pycache__/mine.cpython-314.pyc
Binary file not shown.
Binary file added bench/__pycache__/precision.cpython-314.pyc
Binary file not shown.
Binary file added bench/__pycache__/sample.cpython-314.pyc
Binary file not shown.
Loading
Loading