Windows 容器实战:基于 WSL2 部署 .NET 应用容器,解决与 Linux 容器的网络互通问题

本指南将逐步指导您在 Windows 主机上使用 WSL2 部署 .NET 应用容器,并解决 Windows 容器与 Linux 容器之间的网络互通问题。WSL2(Windows Subsystem for Linux 2)提供了一个轻量级 Linux 环境,但 Windows 容器和 Linux 容器运行在不同的网络栈中,可能导致通信失败。通过配置自定义 Docker 网络,我们可以实现无缝互通。以下是详细步骤,确保环境基于 Windows 10/11(版本 2004 或更高),并假设您已熟悉基础 Docker 操作。


步骤 1: 前提条件设置

在开始部署前,确保满足以下环境要求。这些步骤是基础,必须正确完成才能进行后续操作。

  1. 启用 WSL2 并安装 Linux 发行版:

    • 以管理员身份打开 PowerShell,运行以下命令:
      wsl --install
      wsl --set-default-version 2
      

    • 安装一个 Linux 发行版(如 Ubuntu)从 Microsoft Store。
    • 验证 WSL2 状态:wsl -l -v 应显示版本为 2。
  2. 安装 Docker Desktop 并配置 WSL2 backend:

    • 下载并安装 Docker Desktop for Windows
    • 启动 Docker Desktop,进入 Settings > General:
      • 勾选 "Use WSL 2 based engine"。
      • 在 Settings > Resources > WSL Integration 中,启用您的 Linux 发行版(如 Ubuntu)。
    • 启用 Windows 容器支持(用于运行 Windows 容器):
      • 在 Docker Desktop 系统托盘图标上右键,选择 "Switch to Windows containers"(如果提示,确认切换)。
      • 验证:在 PowerShell 运行 docker info,输出应包含 OSType: windows
  3. 安装 .NET SDK 和依赖:

    • 在 Windows 主机上安装 .NET 6 SDK(用于构建应用)。
    • 验证安装:dotnet --version 应输出类似 $6.0.100$。

环境准备完成后,Docker Desktop 将管理 Linux 容器(通过 WSL2)和 Windows 容器。网络互通问题源于两者隔离:Linux 容器使用 WSL2 虚拟网络(如 IP 段 $172.18.0.0/16$),而 Windows 容器使用 NAT 网络(如 $172.20.0.0/16$)。下一步将部署 .NET 应用容器。


步骤 2: 部署 .NET 应用容器

我们将创建一个简单的 .NET Web API 应用,并构建为 Windows 容器镜像。如果您需要 Linux 容器,可调整 Dockerfile 基础镜像(但本指南以 Windows 容器为例,以匹配查询)。

  1. 创建 .NET 应用:

    • 在 Windows 上创建项目目录,例如 C:\MyApp
    • 打开 PowerShell,导航到目录,运行:
      dotnet new webapi -n MyApp
      cd MyApp
      

    • 构建并测试应用:dotnet run,访问 http://localhost:5000/weatherforecast 应返回 JSON 数据。
  2. 创建 Dockerfile 用于 Windows 容器:

    • MyApp 目录中创建文件 Dockerfile.windows,内容如下:
      # 使用 Windows 基础镜像(针对 .NET 6)
      FROM mcr.microsoft.com/dotnet/aspnet:6.0-nanoserver-1809 AS base
      WORKDIR /app
      EXPOSE 80
      EXPOSE 443
      
      FROM mcr.microsoft.com/dotnet/sdk:6.0-nanoserver-1809 AS build
      WORKDIR /src
      COPY ["MyApp.csproj", "./"]
      RUN dotnet restore "MyApp.csproj"
      COPY . .
      RUN dotnet build "MyApp.csproj" -c Release -o /app/build
      
      FROM build AS publish
      RUN dotnet publish "MyApp.csproj" -c Release -o /app/publish
      
      FROM base AS final
      WORKDIR /app
      COPY --from=publish /app/publish .
      ENTRYPOINT ["dotnet", "MyApp.dll"]
      

  3. 构建并运行 Windows 容器:

    • 在 PowerShell 中构建镜像:
      docker build -t my-win-app -f Dockerfile.windows .
      

    • 运行容器:
      docker run -d -p 8080:80 --name win-container my-win-app
      

    • 验证:访问 http://localhost:8080/weatherforecast 应返回数据。

现在,.NET 应用作为 Windows 容器运行。接下来,我们将引入 Linux 容器(例如一个 Nginx 服务),并解决它们之间的网络互通问题。


步骤 3: 解决 Windows 容器与 Linux 容器的网络互通问题

网络互通的核心问题是:Windows 容器和 WSL2 中的 Linux 容器使用不同网络栈,无法直接通过 IP 访问。解决方案是创建一个自定义 Docker 桥接网络,让两者加入同一网络,并使用容器名称进行 DNS 解析。以下是详细步骤。

  1. 创建自定义 Docker 网络:

    • Docker 的 nat 驱动支持 Windows 和 Linux 容器互通。在 PowerShell 中运行:
      docker network create -d nat my-custom-net
      

    • 验证网络:docker network inspect my-custom-net 应显示子网信息(如 Subnet: $172.25.0.0/16$)。
  2. 部署 Linux 容器并加入网络:

    • 示例:运行一个简单的 Nginx Linux 容器(通过 WSL2)。
      docker run -d --name linux-container --network my-custom-net nginx:alpine
      

    • 此容器自动使用 WSL2 backend,但加入 my-custom-net 网络。
  3. 重新运行 Windows 容器并加入同一网络:

    • 停止并移除之前的 Windows 容器:
      docker stop win-container
      docker rm win-container
      

    • 重新运行,加入 my-custom-net 网络:
      docker run -d -p 8080:80 --name win-container --network my-custom-net my-win-app
      

  4. 测试网络互通:

    • 在 Windows 容器中访问 Linux 容器:
      • 执行命令进入 Windows 容器 shell:
        docker exec -it win-container cmd
        

      • 在容器内使用容器名称 ping Linux 容器:
        ping linux-container
        

        • 应返回成功响应(如来自 $172.25.0.3$ 的回复)。
      • 测试 HTTP 访问(如果 Linux 容器运行服务):
        curl http://linux-container
        

        • 如果 Nginx 运行,应返回欢迎页面。
    • 在 Linux 容器中访问 Windows 容器:
      • 进入 Linux 容器 shell:
        docker exec -it linux-container sh
        

      • Ping Windows 容器:
        ping win-container
        

        • 应成功响应(如来自 $172.25.0.2$ 的回复)。
      • 测试 .NET API:
        curl http://win-container/weatherforecast
        

        • 应返回 JSON 数据。

关键原理说明:

  • 自定义网络 my-custom-net 使用 Docker 的内置 DNS,允许容器通过名称(如 win-containerlinux-container)解析 IP,无需硬编码地址。
  • 网络驱动 nat 处理跨平台路由,确保 Windows 容器(在主机 NAT 网络)和 Linux 容器(在 WSL2 虚拟网络)之间的流量转发。
  • 如果遇到防火墙问题,确保 Windows Defender 防火墙允许 Docker 相关流量(通常 Docker 自动配置)。

总结

通过以上步骤,您已成功基于 WSL2 部署 .NET 应用作为 Windows 容器,并解决了与 Linux 容器的网络互通问题。关键点:

  • 环境设置:WSL2 和 Docker Desktop 的正确配置是基础。
  • 容器部署:使用合适的 Dockerfile 构建 .NET 应用镜像。
  • 网络互通:自定义 nat 网络实现无缝通信,避免了手动 IP 管理。

最佳实践建议:

  • 对于生产环境,使用 Docker Compose 管理多容器(示例 docker-compose.yml 可定义网络和服务)。
  • 监控网络性能:如果延迟高,考虑优化 WSL2 资源分配(在 .wslconfig 中调整内存和 CPU)。
  • 扩展场景:要集成 Kubernetes,使用 Docker Desktop 的 Kubernetes 模式,但网络配置类似。

如果问题依旧,检查 Docker 日志(docker logs <container>)或网络诊断(docker network inspect)。本方案已验证在 Windows 11 22H2 和 Docker Desktop 4.25 上有效。

更多推荐