Skip to content

feat(wslc): add WSL Containers (wslc://) transport, lifecycle integra… - #2659

Open
DavidTavoularis wants to merge 1 commit into
docker-java:mainfrom
DavidTavoularis:feat/wslc-run-lifecycle
Open

feat(wslc): add WSL Containers (wslc://) transport, lifecycle integra…#2659
DavidTavoularis wants to merge 1 commit into
docker-java:mainfrom
DavidTavoularis:feat/wslc-run-lifecycle

Conversation

@DavidTavoularis

Copy link
Copy Markdown

…tion and auto-detection

WSL Containers (wslc) runs dockerd inside a lightweight VM that exposes no Windows named pipe or TCP port; the only host-visible channel is the stdio bridge wslc system session run docker system dial-stdio. This adds first-class wslc support to docker-java.

Transport (docker-java-transport, -transport-httpclient5):

  • WslcSocket: a Socket whose streams are the wslc dial-stdio child process (mirrors NamedPipeSocket; java.util.logging only, no new dependency).
  • ApacheDockerHttpClientImpl: a wslc scheme case plus a WslcSocket branch. Hijacked exec/attach/log streams work unchanged at the HttpClient5 socket level.

Lifecycle integration (docker-java-core):

  • wslc's Windows integration (127.0.0.1 port relay and Windows-path bind mounts) is wired by the wslc control plane only when a container is created/started through the native wslc CLI, not over the Docker API on the same dockerd.
  • WslcLifecycleDockerHttpClient decorates a Docker-API client and reconciles just the affected calls with the wslc CLI, delegating everything else unchanged: POST /containers/create -> wslc create, POST /containers/{id}/start -> wslc start (wires relay+bind), POST /networks/create -> wslc network create, and GET /containers/{id}/json with NetworkSettings.Ports overridden from wslc list (the start relay's real host port differs from the daemon's recorded one).
  • Activated transparently in DockerClientImpl.getInstance only when the host scheme is wslc, so unix/npipe/tcp are unaffected and no extra dependency is needed. Consumers that shade docker-java-core (e.g. Testcontainers) pick it up after a plain rebuild.

Auto-detection (DefaultDockerClientConfig):

  • when DOCKER_HOST is unset, fall back to wslc://localhost on Windows only if the //./pipe/docker_engine pipe is absent and wslc is available (wslc version exit 0, WSLC_EXECUTABLE-overridable), so Docker Desktop/Podman keep winning.

Tests run without a daemon or wslc CLI: WslcSocketTest (executable resolution and connect failure) and WslcLifecycleDockerHttpClientTest (request pass-through, inspect fallback when wslc is unavailable, create-failure handling).

Refs: #2658

…tion and auto-detection

WSL Containers (wslc) runs dockerd inside a lightweight VM that exposes no
Windows named pipe or TCP port; the only host-visible channel is the stdio
bridge `wslc system session run docker system dial-stdio`. This adds first-class
wslc support to docker-java.

Transport (docker-java-transport, -transport-httpclient5):
- WslcSocket: a Socket whose streams are the wslc dial-stdio child process
  (mirrors NamedPipeSocket; java.util.logging only, no new dependency).
- ApacheDockerHttpClientImpl: a `wslc` scheme case plus a WslcSocket branch.
  Hijacked exec/attach/log streams work unchanged at the HttpClient5 socket level.

Lifecycle integration (docker-java-core):
- wslc's Windows integration (127.0.0.1 port relay and Windows-path bind mounts)
  is wired by the wslc control plane only when a container is created/started
  through the native `wslc` CLI, not over the Docker API on the same dockerd.
- WslcLifecycleDockerHttpClient decorates a Docker-API client and reconciles just
  the affected calls with the wslc CLI, delegating everything else unchanged:
  POST /containers/create -> wslc create, POST /containers/{id}/start -> wslc
  start (wires relay+bind), POST /networks/create -> wslc network create, and
  GET /containers/{id}/json with NetworkSettings.Ports overridden from `wslc list`
  (the start relay's real host port differs from the daemon's recorded one).
- Activated transparently in DockerClientImpl.getInstance only when the host
  scheme is wslc, so unix/npipe/tcp are unaffected and no extra dependency is
  needed. Consumers that shade docker-java-core (e.g. Testcontainers) pick it up
  after a plain rebuild.

Auto-detection (DefaultDockerClientConfig):
- when DOCKER_HOST is unset, fall back to wslc://localhost on Windows only if the
  //./pipe/docker_engine pipe is absent and wslc is available (`wslc version`
  exit 0, WSLC_EXECUTABLE-overridable), so Docker Desktop/Podman keep winning.

Tests run without a daemon or wslc CLI: WslcSocketTest (executable resolution and
connect failure) and WslcLifecycleDockerHttpClientTest (request pass-through,
inspect fallback when wslc is unavailable, create-failure handling).

Refs: docker-java#2658

Signed-off-by: David Tavoularis <[email protected]>
Co-authored-by: Claude <[email protected]>
@DavidTavoularis
DavidTavoularis marked this pull request as ready for review July 21, 2026 13:57
@DavidTavoularis
DavidTavoularis requested a review from a team as a code owner July 21, 2026 13:57
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