Skip to content

CLI: Add --mount support for create and run - #41337

Draft
David Bennett (dkbennett) wants to merge 6 commits into
masterfrom
user/dkbennett/mount-v2
Draft

CLI: Add --mount support for create and run#41337
David Bennett (dkbennett) wants to merge 6 commits into
masterfrom
user/dkbennett/mount-v2

Conversation

@dkbennett

Copy link
Copy Markdown
Member

Summary of the Pull Request

Adds Docker-compatible --mount support to wslc container run and wslc container create.

The parser supports bind, named-volume, and tmpfs mounts, including Docker aliases, CSV quoting, read-only mounts, and supported tmpfs options. It produces a common typed mount model, rejects unsupported mount features explicitly, and detects duplicate destinations across --mount, --volume, and --tmpfs.

PR Checklist

  • Closes: Link to issue #xxx
  • Communication: I've discussed this with core contributors already. If work hasn't been agreed, this work might be rejected
  • Tests: Added/updated if needed and all pass
  • Localization: All end user facing strings can be localized
  • Dev docs: Added/updated if needed
  • Documentation updated: If checked, please file a pull request on our docs repo and link it here: #xxx

Detailed Description of the Pull Request / Additional comments

Why parse --mount in WSLC?

This is consistent with how Docker CLI handles --mount, and it is necessary for the same fundamental reason. Docker CLI does not pass the raw --mount key/value string to Docker Engine. Its MountOpt parser validates the CLI grammar and converts it into structured mount.Mount objects, which are sent to the Engine through HostConfig.Mounts. The Engine API consumes typed mount configuration, not Docker CLI syntax.

WSLC must perform the equivalent parsing and translation because its backend boundary is also structured. The runtime and COM transport accept type-specific mount data, not an opaque Docker CLI string that could be forwarded for Docker Engine to interpret.

WSLC additionally has work that must happen before the Engine request can be constructed:

  • It must distinguish bind, named-volume, and tmpfs mounts so each can use the appropriate existing transport.
  • Windows bind sources must be mounted into the utility VM and rewritten to VM-visible paths.
  • Duplicate destinations must be detected before tmpfs entries are placed into a map, where one value could otherwise overwrite another before Docker can reject it.

WSLC also requires an additional capability gate. Docker CLI can represent the full mount.Mount API object, but the current WSLC transport cannot faithfully carry every Docker mount type and option. After applying Docker-compatible syntax validation, WSLC must reject unsupported features before translation. Otherwise, accepted input could lose information silently and reach the Engine with semantics different from what the user requested.

For these reasons, forwarding the fields for Docker Engine to sort out is not possible with the current architecture. Docker CLI itself does not work that way, there is no WSLC backend boundary that accepts the original --mount string, and WSLC needs the parsed values to prepare the backend request.

The common parser is intentionally scoped in two layers:

  1. Parse and validate the CLI grammar using behavior aligned with docker/cli v25.0.3.
  2. Apply a WSLC capability gate that accepts only the options the current runtime can faithfully represent and reports explicit errors for the rest.

This preserves familiar Docker CLI behavior while avoiding silent semantic loss.

The parser lives in src/windows/common and returns a transport-neutral typed mount specification containing the mount type, source, target, read-only state, and supported tmpfs settings. The CLI currently invokes it during argument validation, but it has no dependency on CLI execution types. This keeps the parsing and capability policy reusable if a future SDK or runtime API needs to accept Docker-style mount strings.

An SDK API would normally expose typed mount fields directly rather than requiring callers to construct CLI syntax. That typed API can map to the same common mount model, keeping CLI and SDK behavior aligned while allowing the text-parser call site to move into the runtime later without rewriting the parser.

The source explicitly pins the grammar to docker/cli v25.0.3 so the parsing table can be reviewed when the bundled Docker backend changes.

Implementation

  • Adds a common typed mount::Spec model that is parsed once during CLI argument validation.
  • Moves the Docker-compatible grammar into src/windows/common/MountSpecParsing.cpp and MountSpecParsing.h.
  • Defines the recognized fields and aliases in a declarative table that records each field's option family, whether its bare form is valid, and whether it is supported, unsupported, or value-dependent.
  • Routes bind and named-volume mounts through the existing volume plumbing and tmpfs mounts through the existing tmpfs plumbing.
  • Supports Docker aliases, case handling, CSV quoting, Go-compatible boolean spellings, default volume type, and tmpfs size/mode conversion.
  • Rejects unsupported mount types and options, anonymous volumes, invalid bind or volume sources, and representation limits with localized errors.
  • Normalizes and rejects duplicate destinations across all mount flag forms.
  • Adds table-driven parser coverage with 51 valid and 72 invalid mount specifications.

Validation Steps Performed

  • Full x64 Debug build.
  • WSLCCLIMountParserUnitTests: 5/5 test methods passed, exercising 123 table-driven parser cases.
  • Focused Container_Run_Mount_* end-to-end tests: 5/5 passed.

Add a Docker-style --mount option to `wslc container run` and
`wslc container create`. The flag accepts comma-separated key=value
pairs (type=bind|volume|tmpfs, source/src, target/destination/dst,
readonly/ro) and is routed into the existing volume/tmpfs plumbing.

- Parse --mount into a ParsedMount (ArgumentValidation)
- Register the Mount argument for run/create
- Wire parsed mounts into ContainerOptions (ContainerTasks)
- Add localization strings (MountArgDescription, InvalidMountError)
- Add e2e tests (tmpfs, named volume, readonly-via-inspect, invalid
  type) and update run/create help-text expectations

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI lite review requested due to automatic review settings August 12, 2026 23:07

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds Docker-compatible --mount parsing and plumbing for wslc container run / wslc container create, translating validated mount specs into the existing bind/volume/tmpfs execution paths and adding unit + E2E coverage plus localized error strings.

Changes:

  • Introduces a common mount::Spec model and Docker-grammar --mount parser under src/windows/common/.
  • Wires --mount into argument validation and container option construction, including duplicate-destination rejection across --mount/--volume/--tmpfs.
  • Adds table-driven unit tests and new E2E scenarios for --mount.

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
test/windows/wslc/WSLCCLIMountParserUnitTests.cpp Adds table-driven unit tests for --mount parsing and destination de-duplication behavior.
test/windows/wslc/e2e/WSLCE2EContainerRunTests.cpp Adds E2E coverage for --mount tmpfs/volume/readonly and failure cases.
src/windows/wslc/tasks/ContainerTasks.cpp Plumbs parsed mount specs from CLI args into ContainerOptions and validates uniqueness.
src/windows/wslc/services/ContainerService.cpp Translates mount::Spec into launcher calls for bind/volume/tmpfs.
src/windows/wslc/services/ContainerModel.h Extends ContainerOptions with Mounts and declares destination uniqueness validation.
src/windows/wslc/services/ContainerModel.cpp Reuses named-volume validation from common parser and implements duplicate-destination detection.
src/windows/wslc/commands/ContainerRunCommand.cpp Adds --mount to container run arguments.
src/windows/wslc/commands/ContainerCreateCommand.cpp Adds --mount to container create arguments.
src/windows/wslc/arguments/SpecParsing.cpp Adds a standard header include used by parsing utilities.
src/windows/wslc/arguments/ArgumentValidation.cpp Validates/parses --mount and surfaces localized user-facing errors.
src/windows/wslc/arguments/ArgumentDefinitions.h Declares the new --mount argument in the X-macro table.
src/windows/wslc/arguments/ArgumentConvertedTypes.h Adds the converted type alias mapping for parsed mount specs.
src/windows/common/MountSpecParsing.h Declares the mount grammar version, spec model, and parsing/normalization helpers.
src/windows/common/MountSpecParsing.cpp Implements Docker-compatible --mount parsing and tmpfs option formatting.
src/windows/common/CMakeLists.txt Adds the new common parser sources/headers to the build.
localization/strings/en-US/Resources.resw Adds localized strings for invalid mount syntax and duplicate mount destinations.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/windows/common/MountSpecParsing.cpp
Comment thread test/windows/wslc/e2e/WSLCE2EContainerRunTests.cpp
Comment thread src/windows/common/MountSpecParsing.cpp
Copilot AI review requested due to automatic review settings August 13, 2026 16:14

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 17 changed files in this pull request and generated no new comments.

Suppressed comments (2)

src/windows/common/MountSpecParsing.cpp:583

  • FormatTmpfsOptions also omits an explicitly provided tmpfs-size=0 by skipping size when the parsed value is 0. If the user passes tmpfs-size=0, that intent should be preserved and forwarded (and kept consistent with existing --tmpfs behavior, which can pass size=0).
    if (mount.TmpfsSizeBytes.has_value() && mount.TmpfsSizeBytes.value() != 0)
    {
        options.emplace_back(std::format("size={}", FormatDockerTmpfsSize(mount.TmpfsSizeBytes.value())));
    }

src/windows/common/MountSpecParsing.cpp:579

  • FormatTmpfsOptions drops an explicitly provided tmpfs-mode=0000 because it omits the mode option when the parsed value is 0. That changes user-requested semantics (and differs from --tmpfs, which forwards options verbatim), since mode=0 is a meaningful tmpfs setting.

This issue also appears on line 580 of the same file.

    if (mount.TmpfsMode.has_value() && mount.TmpfsMode.value() != 0)
    {
        options.emplace_back(std::format("mode={:o}", mount.TmpfsMode.value()));
    }

Copilot AI review requested due to automatic review settings August 13, 2026 16:46

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated no new comments.

Suppressed comments (3)

src/windows/common/MountSpecParsing.cpp:14

  • New files should use the repository’s single-line copyright header format (// Copyright (C) Microsoft Corporation. All rights reserved.). This file currently uses the older block header style.
/*++

Copyright (c) Microsoft. All rights reserved.

src/windows/common/MountSpecParsing.h:14

  • New files should use the repository’s single-line copyright header format (// Copyright (C) Microsoft Corporation. All rights reserved.). This header currently uses the older block header style.
/*++

Copyright (c) Microsoft. All rights reserved.

test/windows/wslc/WSLCCLIMountParserUnitTests.cpp:14

  • New files should use the repository’s single-line copyright header format (// Copyright (C) Microsoft Corporation. All rights reserved.). This test file currently uses the older block header style.
/*++

Copyright (c) Microsoft. All rights reserved.

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.

2 participants