WSL 容器网络模式详解:ContainerNetworkingMode 枚举(None / Bridged)的取值、校验与实战
【免费下载链接】WSLWindows Subsystem for Linux项目地址: https://gitcode.com/GitHub_Trending/ws/WSL
导读
ContainerNetworkingMode是 WSL 容器 SDK(WSLC / Microsoft.WSL.Containers)中用于声明容器网络接入方式的枚举类型,它在 WinRT、C++/WinRT、C# 与 C API 四套投影中保持一致:None(隔离、无网络)与Bridged(桥接、接入主机网络)。本文以 cpp/enumerations/containernetworkingmode.md 为核心,结合 wslcsdk.idl 的枚举定义、ContainerSettings.cpp 的严格校验逻辑与 WslcSdkWinRTTests.cpp 的端到端测试,完整说明该枚举的底层数值、语义差异、设置方式、与端口映射的交互规则以及注意事项。读完本文,你将能在自己的 WSLC 应用(或wslc命令行流程)中正确选择并设置容器网络模式。
枚举定义:两个取值,两种网络形态
ContainerNetworkingMode在 WinRT 投影中的定义位于 wslcsdk.idl:
namespace Microsoft.WSL.Containers { enum ContainerNetworkingMode { None = 0, Bridged = 1, }; }底层 C 枚举定义于 wslcsdk.h,语义注释更明确:
typedef enum WslcContainerNetworkingMode { WSLC_CONTAINER_NETWORKING_MODE_NONE = 0, // No networking / isolated WSLC_CONTAINER_NETWORKING_MODE_BRIDGED = 1 } WslcContainerNetworkingMode;| WinRT 枚举值 | C 枚举值 | 底层值 | 语义 |
|---|---|---|---|
ContainerNetworkingMode::None | WSLC_CONTAINER_NETWORKING_MODE_NONE | 0 | 无网络 / 隔离(容器内不创建网络接口) |
ContainerNetworkingMode::Bridged | WSLC_CONTAINER_NETWORKING_MODE_BRIDGED | 1 | 桥接模式(容器接入主机网络,可配合端口映射对外提供服务) |
从源码结构看,该枚举刻意保持精简:当前 WSL 容器 SDK 只开放「完全隔离」与「桥接」两种形态,其余 WSL 发行版级网络模式(如 NAT / Mirrored)属于 WSL 设置应用与 .wslconfig 体系 的范畴,与容器级枚举相互独立,使用时不要混淆。
严格校验:只有 None 与 Bridged 会被接受
关联文档明确指出:winrt_ContainerSettings.cpp只显式校验None与Bridged两个值。对应的实现位于 ContainerSettings.cpp 的NetworkingMode属性 setter:
void ContainerSettings::NetworkingMode(winrt::Windows::Foundation::IReference<winrt::Microsoft::WSL::Containers::ContainerNetworkingMode> const& value) { if (m_containerSettings) { throw winrt::hresult_illegal_state_change(L"Cannot change networking mode after container has been initialized"); } if (value && value.Value() != ContainerNetworkingMode::None && value.Value() != ContainerNetworkingMode::Bridged) { throw winrt::hresult_invalid_argument(L"Invalid networking mode"); } m_networkingMode = value; }这段代码揭示了三条重要规则:
- 取值白名单:任何既不是
None也不是Bridged的数值(包括强转的非法值,如static_cast<ContainerNetworkingMode>(99))都会抛出hresult_invalid_argument(即E_INVALIDARG,HRESULT0x80070057)。该行为已被单元测试直接覆盖:VERIFY_THROWS_HR(containerSettings.NetworkingMode(static_cast<WSLCSDK::ContainerNetworkingMode>(99)), E_INVALIDARG)(见 WslcSdkWinRTTests.cpp)。 - 不可变约束:属性类型是
IReference<ContainerNetworkingMode>(可空引用类型),一旦设置过任何容器设置并完成底层结构转换(ToStructPointer,见 ContainerSettings.cpp),再次修改会抛出hresult_illegal_state_change。因此网络模式必须在创建容器之前确定。 - 允许空值:
value为nullptr时不做校验,表示未显式指定,由 SDK 使用默认行为。
设置最终通过 WslcSetContainerSettingsNetworkingMode 写入 C 层结构,WinRT 值会static_cast为WslcContainerNetworkingMode后传递(见 ContainerSettings.cpp 与 wslcsdk.cpp 中的双向映射)。
两种模式的实际行为差异:eth0 是否存在的端到端验证
None与Bridged的差别在运行态可以直接观察:桥接模式下容器内会出现eth0网络接口,隔离模式下则没有。这一结论并非推测,而是由 WslcSdkWinRTTests.cpp 中的ContainerNetworkingMode测试用例用debian:latest镜像端到端验证的:
// BRIDGED: eth0 interface must be present. { auto output = RunContainerAndWaitForExit( L"debian:latest", {.commandLine = {L"/bin/sh", L"-c", L"[ -d /sys/class/net/eth0 ] && echo 'HAS_ETH0' || echo 'NO_ETH0'"}, .networkingMode = WSLCSDK::ContainerNetworkingMode::Bridged}); VERIFY_ARE_EQUAL(output.StandardOutput, L"HAS_ETH0\n"); } // NONE: eth0 interface must not be present. { auto output = RunContainerAndWaitForExit( L"debian:latest", {.commandLine = {L"/bin/sh", L"-c", L"[ -d /sys/class/net/eth0 ] && echo 'HAS_ETH0' || echo 'NO_ETH0'"}, .networkingMode = WSLCSDK::ContainerNetworkingMode::None}); VERIFY_ARE_EQUAL(output.StandardOutput, L"NO_ETH0\n"); }据此可以将两种模式总结为:
None(隔离):容器完全断开外部网络,适合离线计算、严格隔离的安全场景;没有eth0,因此也无法配合端口映射对外暴露服务。Bridged(桥接):容器获得网络接口并接入主机网络,配合PortMappings可以将容器端口映射到 Windows 侧,供宿主机或其他机器访问。
在 C++/WinRT 中设置网络模式
关联文档给出的最小调用方式为:
containerSettings.NetworkingMode(ContainerNetworkingMode::Bridged);在 C++/WinRT 投影中,NetworkingMode属性的真实类型是winrt::Windows::Foundation::IReference<ContainerNetworkingMode>,因此官方 ContainerSettings 文档 提供了完整的初始化写法(含端口映射与卷配置),可以直接复制使用:
using namespace winrt::Windows::Foundation::Collections; ContainerSettings containerSettings{ L"demo-image:latest" }; containerSettings.Name(L"demo-container"); containerSettings.NetworkingMode( winrt::box_value(ContainerNetworkingMode::Bridged) .as<winrt::Windows::Foundation::IReference<ContainerNetworkingMode>>()); containerSettings.HostName(L"demo-host"); containerSettings.DomainName(L"localdomain"); containerSettings.EnableAutoRemove(false); containerSettings.EnableGpu(false); containerSettings.Privileged(false); auto ports = single_threaded_vector<ContainerPortMapping>(); ports.Append(ContainerPortMapping{ 8080, 80, PortProtocol::TCP }); containerSettings.PortMappings(ports); auto volumes = single_threaded_vector<ContainerVolume>(); volumes.Append(ContainerVolume{ L"C:\\src", L"/src", false }); containerSettings.Volumes(volumes); auto namedVolumes = single_threaded_vector<ContainerNamedVolume>(); namedVolumes.Append(ContainerNamedVolume{ L"cache", L"/cache", false }); containerSettings.NamedVolumes(namedVolumes);设置完成后再通过Session::CreateContainer(containerSettings)创建容器,并调用container.Start()启动。
网络模式与端口映射的交互约束
NetworkingMode不是孤立存在的选项,它与PortMappings存在强约束关系,相关行为同样有测试佐证(见 WslcSdkWinRTTests.cpp):
None+ 端口映射 → 创建即失败:为None模式的容器配置PortMappings会在CreateContainer时抛出E_INVALIDARG:
auto containerSettings = WSLCSDK::ContainerSettings(L"debian:latest"); containerSettings.NetworkingMode(WSLCSDK::ContainerNetworkingMode::None); containerSettings.PortMappings(winrt::single_threaded_vector<WSLCSDK::ContainerPortMapping>( {WSLCSDK::ContainerPortMapping(12342, 8000, WSLCSDK::PortProtocol::TCP)})); VERIFY_THROWS_HR(m_defaultSession.CreateContainer(containerSettings), E_INVALIDARG);Bridged+ 端口映射 → 服务可达:桥接模式下,容器内的 HTTP 服务可以通过 Windows 侧端口访问(测试中先在容器内启动python3 -m http.server 8000,再从宿主机请求http://127.0.0.1:12341并断言返回 200)。可选绑定地址:
ContainerPortMapping还支持通过WindowsAddress绑定到指定 IPv4(如127.0.0.1)或 IPv6(如::1)地址,实现更精细的暴露范围控制。
真实样例:WSLC-NextCloud 中的应用
仓库自带的 WSLC-NextCloud 示例 是Bridged模式的直接落地参考:它通过NetworkingMode = ContainerNetworkingMode.Bridged(Program.cs)配合端口映射,将容器内的 Web 服务暴露给 Windows 宿主机访问,完整演示了「桥接网络 + 端口映射」的标准组合套路。
跨语言投影与相关文档索引
该枚举在仓库的 API 参考文档中覆盖了四套投影,口径完全一致,可按需查阅:
- C++ 枚举参考:cpp/enumerations/containernetworkingmode.md(本文主体)与 cpp/enumerations/index.md
- C# 枚举参考:csharp/enumerations/containernetworkingmode.md
- C 枚举参考:c/enumerations/wslccontainernetworkingmode.md,对应的设置函数为 WslcSetContainerSettingsNetworkingMode
- C++ 设置类参考:cpp/settings-classes/containersettings.md(含完整初始化示例)
- 底层实现与测试:wslcsdk.idl、ContainerSettings.cpp、wslcsdk.h、WslcSdkWinRTTests.cpp
小结与选择建议
- 需要对外提供网络服务、配合
PortMappings暴露端口时,选择Bridged(值1); - 追求网络隔离、无需外部访问时,选择
None(值0); - 枚举只接受这两个值,其他数值一律在属性 setter 处以
E_INVALIDARG拒绝;容器初始化后不可再修改; - 端口映射仅在
Bridged模式下合法,None模式下配置端口映射会在CreateContainer阶段直接失败。
【免费下载链接】WSLWindows Subsystem for Linux项目地址: https://gitcode.com/GitHub_Trending/ws/WSL
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考