Skip to content

docs(readme): resolve the Windows container: self-contradiction - #169

Merged
luthermonson merged 2 commits into
mainfrom
docs/readme-container-consistency
Aug 18, 2026
Merged

docs(readme): resolve the Windows container: self-contradiction#169
luthermonson merged 2 commits into
mainfrom
docs/readme-container-consistency

Conversation

@luthermonson

Copy link
Copy Markdown
Contributor

The README contradicted itself: line ~251 showed a Windows job with container: as a worked example; line ~585 listed that exact key under Known Limitations as blocked. A reader hit one or the other depending on where they landed.

Neither was accurate.

The Known Limitations entry claimed "GitHub's runner binary blocks these on Windows." That string — Container operations are only supported on Linux runnersdoes not exist anywhere in this repo. It originated in docs/_archived/arch/overview.md:313-329, verbatim, including "This is hardcoded in the runner, not something ephemerd can fix." Archived, so low priority, but it will keep re-seeding the error for anyone who mines it.

Nothing in ephemerd refuses container: on Windows: resolveImage (pkg/scheduler/scheduler.go:112-125, :1434-1448) applies the same resolution order for jobOS == "windows", and pkg/github/client.go:274-313 parses container.image with no OS gate.

And the worked example could not be honestly presented as working either — pkg/runtime/image_windows.go:12 makes bare servercore the Windows fallback, and it ships no Docker CLI.

Changes

  • Split into "Linux jobs (OCI containers)" (keeps the Linux worked example) and a new "Windows jobs (OCI containers)". The Windows container: example is removed.
  • Known Limitations rewritten as "unverified, treat as unsupported" with four file-referenced bullets and an explicit no verdict either way. The docker run workaround stays, now caveated that it also needs a Docker CLI in the image and dind.enabled = true.
  • Scoped "the same image runs on every host" to Linux — the Dockerfile above it is FROM ubuntu:24.04, and with the new Windows section adjacent it read as covering Windows-native jobs.

Deliberately left unresolved at the time

Whether Windows container: works end-to-end with a Docker-CLI-equipped image. This was written without a verdict rather than guessing.

#168 has since settled it: it does not, and adding a CLI only moves the failure deeper — the dind sibling path pins linux/<arch>, the overlayfs snapshotter and runc.v2. The "unverified" framing here is now conservative rather than wrong, and #168 adds the explicit 501 refusal plus the [runner.images.<repo>].windows guidance.

The README showed a Windows `container:` job as a worked example under
"Choosing the Image" and, 300 lines later, listed the same key under
Known Limitations as blocked by the GitHub runner binary. Both cannot be
true, and neither was accurate.

The "runner blocks it" claim is wrong: nothing in ephemerd rejects
`container:` on Windows (image resolution in pkg/scheduler resolveImage
is OS-agnostic), and the runner binary does not refuse either — an
observed Windows `container:` job failed looking for docker.exe, which
the servercore default image does not ship.

Whether it works once a Docker CLI is present is genuinely unknown:
dind's bind-mount translation assumes a Linux runner container on
overlayfs with POSIX source paths, and docs/arch/dind-bind-translation.md
lists Windows-native `container:` as a deferred follow-up. ephemerd's own
CI never uses `container:` on any platform.

So: drop the worked example, split the image section into per-OS
subsections, and rewrite the Known Limitations entry to state exactly
what is and is not known rather than asserting a verdict in either
direction. Also scope the "same image runs on every host" line to Linux
images, which is what it always meant.
…sharpen it

Two changes to the Known Limitations entry.

Merge-order hazard. The entry asserted "ephemerd has no code path that
rejects them on Windows". True on main today, false the moment PR #168
lands its 501 gate for Windows sibling-container creation. Rewritten to
describe the outcome (the job fails; where it fails depends on image and
version) rather than the absence of a code path, so it reads correctly
whichever of the two merges second. The deep-failure bullet now says the
symptom is "either an explicit not-implemented from the daemon or a raw
snapshotter/runtime error out of containerd", which covers both worlds.

Sharpened verdict. The previous closing said "no verdict either way",
which was right when written but undersold the evidence now confirmed
against main: handleContainerCreate pins linux/<arch>, the overlayfs
snapshotter and io.containerd.runc.v2 unconditionally
(pkg/dind/containers.go), and Windows containerd only offers the
windows/windows-lcow snapshotters (pkg/dind/cleanup.go). A Docker CLI
genuinely only moves the failure deeper, so the entry now says "not
supported" and explains why.

That same pinning also condemns the `docker run` workaround this section
had recommended since forever — container creation through the fake
daemon is Linux-only, so the workaround fails on a Windows-native job for
the same reason the thing it worked around does. Removed it rather than
keep pointing people at it. `docker build`/`docker push` are unaffected
(BuildKit path, exercised on Windows by build-images.yml), and Linux jobs
are unaffected everywhere, so both are called out.

Also scoped the adjacent dind entry, which claimed `docker run` works
with no OS qualification and described the socket transport as if
/var/run/docker.sock were universal, and scoped the "One Image, Every
Host" line at :91 to Linux images (same defect already fixed at :585).
@luthermonson
luthermonson merged commit c8f17c3 into main Aug 18, 2026
4 checks 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