WSL C SDK 容器配置指南:深入解析 ContainerSettings 与 WSLC 容器创建全流程
发布时间:2026/9/10 17:44:38来源:尧图网络
WSL C# SDK 容器配置指南深入解析 ContainerSettings 与 WSLC 容器创建全流程【免费下载链接】WSLWindows Subsystem for Linux项目地址: https://gitcode.com/GitHub_Trending/ws/WSL本文以 WSLWindows Subsystem for Linux开源仓库中 C#/WinRT 版 WSLC SDK 的ContainerSettings类文档为核心系统讲解容器创建前的完整配置模型从属性语义、配套数据类型与枚举到ContainerSettings如何转换为底层原生WslcContainerSettings结构体并作用于容器创建。读者读完将掌握用 C# 配置镜像、网络、端口映射、卷挂载与 init 进程并驱动一个完整容器生命周期的实战能力。ContainerSettings 在 WSLC SDK 中的定位ContainerSettings是 WSLCWSL ContainersC# SDK 中用于在容器创建之前完成全部配置的设置类Settings Class。它不属于运行时对象而是「创建参数容器」你通过它描述镜像、名称、init 进程、网络模式、端口发布、卷挂载等所有期望然后把它交给会话Session去真正创建容器。相关文档与源码位置官方 API 文档containersettings.md设置类索引settings-classes/index.mdC# 投影源码src/windows/WslcSDK/csharp/Projection.csWinRT 实现src/windows/WslcSDK/winrt/ContainerSettings.h 与 src/windows/WslcSDK/winrt/ContainerSettings.cpp类型定义IDLsrc/windows/WslcSDK/winrt/wslcsdk.idl典型的使用路径是new ContainerSettings(imageName)→ 设置各属性 →session.CreateContainer(containerSettings)。容器创建完成后ContainerSettings的使命即告完成后续操作Start / Stop / Delete / CreateProcess都由返回的 Container 对象接管。类定义与属性全景官方文档给出的类定义如下public sealed class ContainerSettings { public ContainerSettings(string imageName); public string ImageName { get; set; } public string Name { get; set; } public ProcessSettings InitProcess { get; set; } public ContainerNetworkingMode? NetworkingMode { get; set; } public string HostName { get; set; } public string DomainName { get; set; } public bool EnableAutoRemove { get; set; } public bool EnableGpu { get; set; } public bool Privileged { get; set; } public IListContainerPortMapping PortMappings { get; set; } public IListContainerVolume Volumes { get; set; } public IListContainerNamedVolume NamedVolumes { get; set; } }构造与核心标识属性属性类型说明ImageNamestring容器镜像名称如docker.io/library/alpine:latest由构造函数必填传入也可通过属性重新赋值Namestring容器自定义名称便于识别与后续引用HostNamestring容器内的主机名DomainNamestring容器内域名从 ContainerSettings.cpp 可以看到构造函数会立即校验镜像名ContainerSettings::ContainerSettings(hstring const imageName) : m_imageName(winrt::to_string(imageName)) { if (imageName.empty()) { throw winrt::hresult_invalid_argument(LImage name cannot be empty); } }即镜像名为空时直接抛出E_INVALIDARGC# 中表现为ArgumentException。ImageName与Name的 setter 同样做了空值校验与状态保护。行为与能力属性属性类型默认说明InitProcessProcessSettingsnull可选容器启动时执行的 init 进程配置可选不设置则容器不绑定 init 进程NetworkingModeContainerNetworkingMode?null网络模式null表示沿用默认行为即不显式覆盖网络设置EnableAutoRemoveboolfalse容器退出后是否自动移除EnableGpuboolfalse是否启用 GPU 直通/加速Privilegedboolfalse是否以特权模式运行值得注意NetworkingMode的可空语义文档明确注释「nullmeans leave default behavior」。这与普通bool?截然不同——显式传ContainerNetworkingMode.None是主动选择「无网络」模式而传null是「不干预、交给默认策略」。二者不可混为一谈。集合属性属性类型说明PortMappingsIListContainerPortMapping要发布的端口映射列表Windows 端口 ↔ 容器端口VolumesIListContainerVolumeWindows 目录 → 容器目录的绑定挂载列表NamedVolumesIListContainerNamedVolume会话管理的命名 VHD 卷 → 容器目录的挂载列表官方文档特别强调PortMappings、Volumes、NamedVolumes都是可变集合mutable collections。这意味着你可以在构造ContainerSettings之后继续向集合中添加元素而不必一次性在对象初始化器中写死全部条目var settings new ContainerSettings(docker.io/library/alpine:latest); settings.PortMappings.Add(new ContainerPortMapping(8080, 80, PortProtocol.TCP)); settings.Volumes.Add(new ContainerVolume(C:\data, /workspace/data, readOnly: false)); settings.NamedVolumes.Add(new ContainerNamedVolume(cache, /var/cache/app, readOnly: false));从 WinRT 实现看三个集合成员默认初始化为winrt::single_threaded_vector见 ContainerSettings.h因此即使从未显式赋值返回的也是可用空集合可直接Add。从 C# 属性到原生结构体底层转换机制ContainerSettings本质上是一层 WinRT 封装。真正传递给底层创建逻辑的是原生 C 结构体WslcContainerSettings。转换发生在ToStructPointer()方法中ContainerSettings.cpp整个过程只执行一次并且揭示了几个重要的运行时行为1. 惰性初始化与「初始化后不可变」保护ToStructPointer()使用std::make_uniqueWslcContainerSettings()惰性构建结构体首次调用后m_containerSettings非空。所有 setter 都会检查m_containerSettings一旦结构体已被生成即设置被「固化」再次修改任何属性都会抛出hresult_illegal_state_changeC# 中表现为InvalidOperationExceptionvoid ContainerSettings::ImageName(hstring const value) { if (m_containerSettings) { throw winrt::hresult_illegal_state_change(LCannot change image name after container has been initialized); } ... }同理适用于Name、InitProcess、NetworkingMode、HostName、DomainName及三个集合属性。可以推断一旦ContainerSettings被传入CreateContainer完成结构体固化就应当将其视为只读任何后续修改都会引发异常。实践建议是在创建容器前完成全部配置。2. 布尔属性底层是标志位EnableAutoRemove、EnableGpu、Privileged三个布尔属性并非独立字段而是通过WI_IsFlagSet/WI_UpdateFlag操作一个WslcContainerFlags位掩码EnableAutoRemove↔WSLC_CONTAINER_FLAG_AUTO_REMOVEEnableGpu↔WSLC_CONTAINER_FLAG_ENABLE_GPUPrivileged↔WSLC_CONTAINER_FLAG_PRIVILEGED最终在ToStructPointer()中通过WslcSetContainerSettingsFlags(m_containerSettings.get(), m_containerFlags)一次性写入。这套标志位与镜像名、网络模式、挂载等一起构成了创建容器所需的完整参数集。3. 集合校验拒绝空元素在将托管集合转换为原生数组时实现会逐个元素检查遇到null元素即抛错for (auto const portMapping : m_portMappings) { if (!portMapping) { throw winrt::hresult_error(E_POINTER, LPort mappings collection contains a null element); } m_portMappingsStructs.push_back(GetStruct(portMapping)); }Volumes、NamedVolumes的处理完全相同。这意味着不要在集合中放入 null 元素否则会在创建容器时抛出异常。4. 空集合与可选属性被跳过ToStructPointer()对每个可选维度都有「非空才设置」的保护Name、HostName、DomainName为空字符串时跳过对应的WslcSetContainerSettings*调用集合Size() 0时跳过数组转换。也就是说未配置的可选项不会污染底层结构体全部交由默认行为处理。配套数据类型端口映射与卷挂载ContainerSettings的三个集合属性分别由三个数据类支撑各自的 API 文档与定义如下。ContainerPortMapping发布端口定义见 containerportmapping.mdusing Windows.Networking; public sealed class ContainerPortMapping { public ContainerPortMapping(ushort windowsPort, ushort containerPort, PortProtocol protocol); public ushort WindowsPort { get; set; } public ushort ContainerPort { get; set; } public PortProtocol Protocol { get; set; } public HostName WindowsAddress { get; set; } }关键约束WindowsAddress已实现文档明确标注 implemented用于指定 Windows 侧绑定地址只接受HostNameType.Ipv4与HostNameType.Ipv6DNS 域名会被拒绝WindowsAddress null表示使用默认宿主绑定地址。典型用法是显式绑定到回环地址避免将端口暴露到所有网卡using Windows.Networking; var mapping new ContainerPortMapping(8080, 80, PortProtocol.TCP) { WindowsAddress new HostName(127.0.0.1) };PortProtocol枚举见 portprotocol.mdpublic enum PortProtocol { TCP 0, UDP 1 }ContainerVolumeWindows 目录绑定挂载定义见 containervolume.md将 Windows 路径映射进容器。public sealed class ContainerVolume { public ContainerVolume(string windowsPath, string containerPath, bool readOnly); public string WindowsPath { get; set; } public string ContainerPath { get; set; } public bool ReadOnly { get; set; } }示例var volume new ContainerVolume(C:\data, /workspace/data, readOnly: false);WindowsPath使用 Windows 风格路径如C:\dataContainerPath使用容器内 Linux 路径如/workspace/dataReadOnly控制是否只读挂载。ContainerNamedVolume会话管理的命名卷定义见 containernamedvolume.md映射一个由会话Session管理的命名 VHD 卷到容器内。public sealed class ContainerNamedVolume { public ContainerNamedVolume(string name, string containerPath, bool readOnly); public string Name { get; set; } public string ContainerPath { get; set; } public bool ReadOnly { get; set; } }示例var namedVolume new ContainerNamedVolume(cache, /var/cache/app, readOnly: false);与ContainerVolume的区别在于数据存储介质ContainerVolume直接绑定 Windows 宿主目录而ContainerNamedVolume使用会话管理的 VHD 卷按名称引用更适合存放容器生命周期之外需要持久化、又不想散落在 Windows 文件系统中的数据如缓存、数据库文件。配套枚举网络模式与进程输出ContainerSettings中用到的枚举定义如下。ContainerNetworkingMode见 containernetworkingmode.mdpublic enum ContainerNetworkingMode { None 0, Bridged 1 }None容器无网络或关闭显式网络Bridged桥接模式容器通过宿主网络桥接对外通信。在 WinRT 实现中ContainerSettings.cppsetter 会校验传入值必须是None或Bridged二者之一否则抛E_INVALIDARG。当属性为null时不做任何设置交给默认行为。ProcessOutputModeInitProcess的类型是 ProcessSettings其中OutputMode决定 init 进程的输出如何被消费public enum ProcessOutputMode { Discard 0, Stream 1, Event 2 }Discard丢弃输出Stream通过GetOutputStream(...)读取输出流Event通过OutputReceived/ErrorReceived事件接收输出。文档要点init 进程由Container.Start()启动而非Process.Start()当InitProcess.OutputMode为Event或Stream时Container.Start()会自动请求原生 attach以便把输出回传到托管侧见 container.md。此外CommandLine在调用进程启动前必须非空。实战示例完整配置一个容器官方文档在 containersettings.md 中给出了一个综合配置示例融合了 init 进程、网络模式、自动移除、端口映射与两种卷挂载var init new ProcessSettings { CommandLine new Liststring { /bin/sh, -c, echo hello from init }, OutputMode ProcessOutputMode.Event }; var containerSettings new ContainerSettings(docker.io/library/alpine:latest) { Name demo-container, InitProcess init, NetworkingMode ContainerNetworkingMode.Bridged, EnableAutoRemove true, PortMappings new ListContainerPortMapping { new(8080, 80, PortProtocol.TCP) }, Volumes new ListContainerVolume { new(C:\data, /workspace/data, false) }, NamedVolumes new ListContainerNamedVolume { new(cache, /var/cache/app, false) } };这段代码一次性覆盖了ContainerSettings的全部能力维度以alpine:latest为镜像、命名为demo-container、桥接网络、退出自动清理、8080→80 的 TCP 端口发布、Windows 目录绑定挂载以及命名 VHD 卷挂载同时通过InitProcess让容器启动时执行/bin/sh -c echo hello from init并把输出以事件方式交付给调用方。结合完整生命周期使用将上述配置放入一个完整生命周期参考 end-to-end-example.md 与 container.md检查前提WslcService.GetMissingComponents()确认 WSL 组件齐全缺失时提示wsl --install创建会话new Session(new SessionSettings(MyApp, C:\WslcData) { CpuCount 4, MemorySizeInMB 4096 })拉取镜像session.PullImageAsync(new PullImageOptions(docker.io/library/alpine:latest))配置ContainerSettings含InitProcess创建容器var container session.CreateContainer(containerSettings);订阅 init 进程的OutputReceived与Exited事件必须在Start()之前订阅container.Start()启动容器与 init 进程等待 init 进程退出读取退出码清理container.Stop(Signal.SIGTERM, TimeSpan.FromSeconds(10))、container.Delete(DeleteContainerOption.None)、session.Terminate()。其中关键点是Container.CreateProcess(...)可基于同一容器创建次级进程ProcessSettings.CommandLine非空即可而Container.Inspect()返回原始 inspect JSON 字符串方便调试容器状态。注意事项与易错点汇总综合官方文档注释与 ContainerSettings.cpp 实现使用时有以下要点创建前完成配置ContainerSettings在底层结构体固化后所有属性不可再改抛InvalidOperationException所有配置必须在传入CreateContainer之前完成。镜像名不能为空构造函数与ImageNamesetter 均校验空字符串并抛参数异常。NetworkingMode的可空语义null 默认行为显式None/Bridged 主动指定。Bridged是文档示例中推荐的网络模式。集合可变但元素不可为 null三个集合属性可直接Add但任何 null 元素都会在创建容器时抛异常。WindowsAddress仅接受 IPContainerPortMapping.WindowsAddress只允许 IPv4 / IPv6HostName传 DNS 名称会被拒绝null表示默认绑定地址。InitProcess是可选项不设置则Container.InitProcess不可用见 container.md 注释设置了且输出模式为 Event/Stream 时Start()会自动 attach 输出。init 进程的启动时机init 进程由Container.Start()启动而非Process.Start()事件订阅必须在Start()之前完成避免漏掉输出与退出事件。两种卷的差异ContainerVolume绑定 Windows 宿主路径ContainerNamedVolume引用会话管理的 VHD 命名卷持久化场景按需选择。总结ContainerSettings是 WSLC C# SDK 中连接「容器意图」与「容器实体」的配置枢纽它把镜像、名称、init 进程、网络模式、自动清理、GPU、特权、端口映射、目录挂载与命名卷挂载统一收敛到一个可校验、可冻结的设置对象中再通过ToStructPointer()的惰性固化为原生WslcContainerSettings交给创建流程。理解其属性语义、可空约定与「初始化后不可变」约束是写出健壮、可预测的 WSL 容器编排代码的前提。如需继续深入建议阅读 settings-classes/index.md 了解全部设置类SessionSettings、VhdOptions、PullImageOptions等并结合 overview.md 与 end-to-end-example.md 串联完整调用链底层 C 接口定义可查看 src/windows/WslcSDK/winrt/wslcsdk.idl。【免费下载链接】WSLWindows Subsystem for Linux项目地址: https://gitcode.com/GitHub_Trending/ws/WSL创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网