Skip to content

Add support for WSL Containers runtime#194

Open
antsok wants to merge 2 commits into
microsoft:mainfrom
antsok:feature/support-wslc
Open

Add support for WSL Containers runtime#194
antsok wants to merge 2 commits into
microsoft:mainfrom
antsok:feature/support-wslc

Conversation

@antsok

@antsok antsok commented Jun 30, 2026

Copy link
Copy Markdown

Fixes #179 (Iteration 1); to be followed after microsoft/WSL#40835 is completed.

Add wslc container runtime support

Summary

Adds a new wslc container runtime to DCP, alongside the existing docker and podman runtimes. wslc is the WSL container CLI (buildkit backend) that runs containers on Windows without Docker Desktop. This PR plumbs a full wslc orchestrator through DCP's container/network abstractions and introduces a content-addressed derived-image cache so that per-container customization layers (config files, certificates) are baked once and reused across runs instead of being rebuilt every time.

Motivation

  • Enable running Aspire/DCP container workloads on Windows via WSL containers (wslc), with no dependency on Docker Desktop.
  • wslc has a session-wide volume-mount limit and no container cp primitive, so the existing "copy files into a created container" flow does not translate directly. This PR adapts DCP's file-injection and image-customization model to those constraints.

What's included

New wslc orchestrator

  • internal/wslc/cli_orchestrator.go — full ContainerOrchestrator / NetworkOrchestrator implementation driving the wslc CLI: container/network/volume/image lifecycle, image pull/inspect/build, log streaming, exec, and terminal (PTY) support.
  • CLI error-shape detection (not found / already exists / runtime-not-healthy / missing tar) mapped onto DCP's shared sentinel errors (ErrNotFound, ErrAlreadyExists).
  • Registered in the runtime factory map and the --container-runtime flag (docker, podman, wslc).

Content-addressed derived-image cache

  • When a container needs extra layers (e.g. injected config files or dev certificates), DCP now builds a derived image tagged as:

    <baseRepo>:<originalTag>-dcp-<sha256(baseImageContentID + layerDigests)>
    
  • The cache key folds in the base image's immutable content ID (not its tag), so mutable tags like latest are handled correctly — a registry-side move of latest to new content yields a different key and triggers a rebuild.

  • Before building, the controller probes for the derived tag and reuses it on a hit, skipping wslc build entirely. This keeps wslc's session-wide build-context/volume-mount usage bounded across repeated runs.

  • Tar layer generation is deterministic (fixed mod-times, sorted paths) so identical inputs always produce the same digest.

Orchestrator abstraction changes

  • CreateFiles gains CreateFilesRequiresRunningContainer() — runtimes that inject files by exec-ing tar inside the container (wslc) return true, so the controller defers the copy until the container is running; Docker/Podman (cp) return false.
  • CreateContainerOptions gains CreationNetworks (per-network aliases attached at creation time) for runtimes that can only attach networks at creation.
  • New shared helper BuildCreateFilesTar(...) produces an in-memory tar (usable both as a container file-copy payload and as an image layer).

Files changed

Area Files
New runtime internal/wslc/cli_orchestrator.go, internal/wslc/cli_orchestrator_test.go
Runtime wiring internal/containers/flags/container_runtime.go, internal/containers/runtimes/runtime.go
Orchestrator API internal/containers/container_orchestrator.go, internal/containers/containers_common.go (+ test), internal/containers/network_orchestrator.go
Cache + controller controllers/container_controller.go, controllers/container_image_layer_cache_test.go
Existing runtimes internal/docker/cli_orchestrator.go, internal/podman/cli_orchestrator.go
Test utilities internal/testutil/ctrlutil/test_container_orchestrator.go
Build Makefile (PowerShell SHELLFLAGS fix for Windows)

Testing

  • Unit tests for the derived-image cache covering the full build/skip matrix:
    • identical base + layers ⇒ reuse cached image (no rebuild);
    • changed layer content / rotated certificate ⇒ rebuild;
    • different base image content ID ⇒ different derived tag;
    • derived-tag format for plain repos, registries-with-port, and digest-only references.
  • Unit tests for the wslc orchestrator (CLI argument construction, error mapping, parsing).
  • go build ./..., make lint (0 issues), and package tests pass.
  • End-to-end validated with a real Aspire app (6 containers: Redis + RedisInsight + Redis Commander, Postgres + pgAdmin + pgweb) on wslc, confirming cache hits across repeated runs (zero rebuilds when inputs are unchanged) and correct behavior across stop/restart.

Notes for reviewers

  • The cache key is intentionally keyed on base image content ID, not tag, to avoid stale reuse with mutable tags. With PullPolicyAlways, the base image is re-pulled before its content ID is read (so registry-side latest moves are detected); with the default/Never policies, the locally present base content ID is used, matching normal create semantics.
  • No changes to public API types under api/v1 (the regenerated zz_generated.* files have no content delta).
  • File/certificate copying should be changed when wslc supports 'cp' command

antsok added 2 commits June 30, 2026 13:17
…ge cache

Introduces the wslc CLI orchestrator and wires it through the container/network orchestrator abstractions and runtime flag. Adds a content-addressed derived-image cache that skips rebuilds when the base image content and image layers are unchanged, keyed on the base image's content ID rather than its (possibly mutable) tag.
@danegsta

Copy link
Copy Markdown
Member

Hey @antsok, thanks for the PR; we're actively working with the WSL team to close some of the gaps in wslc that you're working around in this PR (such as microsoft/WSL#40835 that you mentioned). The WSL team is targeting support for cp as well as bind mounts and several other core features around August.

Given that we expect most of the blocking issues to be resolved soon, we'd prefer not to make any changes to the container controller or shared orchestrator definitions to workaround the current limitations just to back out those changes in a month or two. A few of the workarounds such as delaying file copy operations would be fundamentally incompatible with some Aspire usage anyway as we specifically use the feature to copy files that need to be in place before we run the containers.

If you're still eager to get initial wslc support available to play with before the WSL team makes their changes, we'd prefer an implementation that no-oped and logged an error for unsupported scenarios such as bind mounts and cp operations. While there'd be some gaps in support (HTTPS/certificate trust in containers won't work without full cp support, for example) it'd avoid churn to our runtime contracts.

@antsok

antsok commented Jun 30, 2026

Copy link
Copy Markdown
Author

Hi @danegsta , I am happy to wait if the WSL team is adding cp soon. My PR works around certificate problem by layering the images with generated certs. cp is much cleaner :)

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.

Add support for WSL container runtime

2 participants