containerd / containerd/containerd
Windows: make the CimFS (and block-CIM) snapshotter usable without manual multi-place config
- Dominant language
- Go
- Stars
- 21.3k
- Forks
- 4.1k
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 95
Description
### Summary
Using the `cimfs` snapshotter on Windows works, but only after wiring it into **two** separate config sections, and a wrong/over-eager entry fails daemon startup. This makes it hard for downstreams (dockerd, nerdctl) to enable, even though the snapshotter, differ, and runtime are all complete. Proposal: default-wire `cimfs`/`blockcim` when the OS supports them.
### It works today — with manual config
On Windows 11 25H2 (build 26200), containerd v2.3.1, `cimfs` end-to-end via `ctr`:
```toml
[plugins."io.containerd.service.v1.diff-service"]
default = ["cimfs", "windows", "windows-lcow"]
[[plugins."io.containerd.transfer.v1.local".unpack_config]]
platform = "windows/amd64"
snapshotter = "windows"
differ = "windows"
[[plugins."io.containerd.transfer.v1.local".unpack_config]]
platform = "windows/amd64"
snapshotter = "cimfs"
differ = "cimfs"
```
```
ctr images pull --snapshotter cimfs mcr.microsoft.com/windows/nanoserver:ltsc2025 # unpacks via the cimfs differ
ctr run --rm --snapshotter cimfs mcr.microsoft.com/windows/nanoserver:ltsc2025 t cmd /c "echo ok" # -> ok, CimFS rootfs mounted by runhcs
```
### The friction
1. **Two independent knobs.** The transfer-service path (`ctr`) needs a `cimfs` entry in `io.containerd.transfer.v1.local.unpack_config`; the diff-service path (`client.Pull` / dockerd / nerdctl-run) needs `cimfs` in `io.containerd.service.v1.diff-service.default`. Miss either and it silently falls back or errors (`no unpack platforms defined`, or `mount layer type must be lcow-layer`).
2. **Defining `unpack_config` replaces the default** — so you must re-list the `windows` entry too, or normal pulls break.
3. **The diff-service order hard-fails startup** if a listed differ isn't loaded (`needed differ not loaded: cimfs`). Since `cimfs`/`blockcim` skip-load on OSes that don't support them, you can't just ship one static config across Windows versions.
### Proposal
When `cimfs.IsCimFSSupported()` (resp. `IsBlockCimSupported()`) is true, include `cimfs` (resp. `blockcim`) in the **default** Windows `diff-service` order and add a matching **default** `unpack_config` entry — so a client only needs `--snapshotter cimfs`. This is safe:
- the `cimfs` differ returns `ErrNotImplemented` for non-CIM mounts and falls through to `windows`;
- the `unpack_config` `cimfs` entry only activates when `--snapshotter cimfs` is requested.
Optionally, make a listed-but-unloaded differ in the order **skip gracefully** instead of failing startup, so a single config degrades cleanly across Windows builds.
### block-CIM is already implemented
`blockcim` snapshotter + differ are present and complete; they just skip-load on GA Windows (hcsshim gates to build ≥ 27766, currently a placeholder pending an official build). Handling both now means block-CIM "just works" the day Windows enables it.
### Downstream impact
This currently blocks Docker Engine from offering CimFS at all (it can't inject managed-containerd config): moby/moby#53063. And `nerdctl run` can't use it either: containerd/nerdctl#5065.
Contributor guide
Research direction
Start by tracing the Windows diff-service defaults and transfer-service unpack_config handling, including IsCimFSSupported and IsBlockCimSupported. Exercise the ctr and client.Pull paths with cimfs, and verify that supported Windows builds work without manual config while unsupported builds do not fail daemon startup.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- backend, infrastructure
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100