上个月翻出一台搁置了大半年的测试笔记本系统还停在win10 v2004任务是在上面把Docker跑起来。以前遇到这种需求我的第一反应是装虚拟机或者用Docker Toolbox那种老路但那种割裂感用过的人都懂容器在虚拟机里跑Windows 这边共享目录又慢又绕文件权限能折腾一下午。这次我换了思路在win10 v2004下开启WSL2部署Docker用系统自带的轻量虚拟化层跑一个 Linux 发行版Docker 直接装在里面。说句实话整套方案跑起来之后那台老机器的启动速度和资源占用都让我有点意外日常操作也基本都在终端里完成不需要再打开任何图形化的虚拟机界面。这篇文章不聊宏大概念只讲我怎么一步步装的、为什么这么选以及跑起来之后那些文档里不会写清楚的细节。如果你正好也有一台停留在 v2004 的 Windows 电脑想在本地跑 Docker这篇应该能帮你省点时间。1. 为什么这台win10 v2004测试机最终选了WSL2跑Docker1.1 旧方案各有各的难处在进入安装步骤之前先说说我为什么放弃了更传统的做法。很多人一想到 Windows 上跑 Docker脑子里跳出来的还是 Docker Toolbox。这套东西本质上是在 VirtualBox 里启动一个叫 boot2docker 的轻量 Linux 虚拟机然后所有 Docker 命令都转发到虚拟机里执行。听起来可行实际用过的人都知道痛点在哪儿Windows 和虚拟机之间共享目录的速度让人着急大量小文件的读写更是慢得离谱虚拟机自己的 IP 还不稳定端口转发时不时要重新配置。我已经不止一次遇到容器起来了浏览器却访问不了映射端口的情况。另一条路是开启 Hyper-V 完整虚拟化。这个方案在性能和稳定性上确实比 Toolbox 强不少但代价也很明显。Hyper-V 一旦启用很可能影响 VirtualBox、VMware 这些其他虚拟机软件的正常运行还容易出现 Windows 功能之间互相干扰。更要命的是完整的 Hyper-V 对系统版本有要求家庭版默认不提供想用还得绕路。为了跑一个 Docker 就去动整个系统的虚拟化层怎么看都有点重。1.2 WSL2到底改了什么WSL2 的思路完全不同。它不是像 Hyper-V 那样给你一个完整可操控的虚拟机桌面而是提供了一个以命令行为核心的轻量 Linux 运行环境。WSL1 时代这个环境靠的是系统调用翻译兼容性有限很多依赖内核特性的软件根本跑不起来Docker 就是其中之一。WSL2 改成了真正的小型虚拟机自带完整 Linux 内核Docker 需要的 cgroups、iptables、网络命名空间这些基础能力全都具备。于是部署 Docker 这件事第一次在 Windows 上变得和在一台普通 Linux 服务器上一样自然。这台 win10 v2004 测试机的配置其实很一般8GB 内存、普通 SATA 固态。WSL2 跑起来之后我最直观的感受是不需要一个常年驻留的图形界面也不需要给整个虚拟机分配固定内存WSL2 是按需启动的用的时候进终端不用了它自己释放资源。这种轻量感是传统虚拟机方案给不了的。而且 v2004 正好是第一波正式支持 WSL2 的系统版本虽然现在看着旧但当时围绕这套方案的资料已经比较成熟踩坑也有迹可循。2. 动手前的三项环境核对版本号、虚拟化开关与磁盘2.1 win10 v2004的版本号到底怎么认很多人嘴上说着 v2004实际上自己的系统根本不是这个版本。开始之前建议先按Win R输入winver回车看弹出窗口里的版本信息。v2004 对应的内部版本号是 19041比如显示版本 2004OS 内部版本 19041.xxx就没问题。如果你拿到的是 1903 或 1909WSL2 的功能支持会差一截内核更新包的对应关系也不一样最好先把系统补丁升上去再继续。这里有个容易忽略的细节v2004 这个版本的 WSL2 支持和我们现在在 Win11 上看到的开箱即用不一样。Win11 里 WSL2 基本可以作为一个组件直接启用但 v2004 时代启用之后往往还需要手动安装一个内核更新包。后面我会单独说这一步别跳过去。2.2 BIOS虚拟化在任务管理器里就能查WSL2 说到底还是虚拟化技术CPU 的虚拟化开关必须打开否则后面怎么折腾都白搭。检查方法很简单打开任务管理器切到性能标签页选中 CPU看右下角的虚拟化字段是否显示已启用。如果显示已禁用就需要重启进 BIOS/UEFI找到类似 Intel Virtualization Technology 或 SVM Mode 的选项把它设为 Enabled保存退出。这一步在商用机和二手笔记本上特别容易踩坑有些出厂设置默认是关闭的。我那次在测试机上就没想太多直接开始了结果 WSL2 转换版本时卡了十几分钟后来查了一圈才发现虚拟化没开白等了半天。2.3 磁盘格式影响发行版安装位置WSL2 的发行版会以虚拟磁盘文件的形式存在默认放在系统盘的用户目录里。C 盘空间紧张的话这一步最好提前规划。具体位置大概是C:\Users\你的用户名\AppData\Local\Packages\下面某个发行版相关的目录。建议安装前先确认 C 盘至少有 10GB 空闲空间。如果之后 Docker 镜像多了虚拟磁盘文件还会继续膨胀。我在这台测试机上预留了 20GB后来跑了十几个镜像也没有紧张。真到了空间不够的那天可以用wsl --export和wsl --import把发行版迁移到其他盘但这个过程需要先导出再导入比较费时间能提前避免就别往后拖。3. 把WSL2一步步开启功能项、内核包和默认版本3.1 图形界面启用两项Windows功能在开始菜单搜索启用或关闭 Windows 功能打开后找到两个选项都勾上适用于 Linux 的 Windows 子系统虚拟机平台勾选完成后系统会提示重启这一步不要偷懒因为虚拟机平台这个功能标记虽然显示启用了但要等重启之后才真正生效。我当时就是因为没重启后面执行wsl --set-version一直卡住浪费了不少时间。注意这里不需要勾选 Hyper-V。WSL2 依赖的虚拟机平台和完整的 Hyper-V 是两回事。如果你只是为了跑 Docker勾多了反而可能引入和其他虚拟机软件的冲突。3.2 PowerShell备用路径与确认状态如果你用的系统版本比较特殊图形界面里找不到这两个功能选项或者操作时报错可以改用管理员身份的 PowerShell 执行两条命令Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform执行完同样需要重启。重启之后可以用下面的命令确认功能状态Get-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux Get-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform输出里的State只要显示Enabled就说明功能已经打开了。3.3 手动安装内核更新包这一步是 v2004 时代最容易漏掉的地方。从官方渠道获取名为wsl_update_x64.msi的内核更新包下载之后以管理员身份运行。运行完毕就完成了 WSL2 内核的安装。很多教程只讲了功能启用没有提这个包结果用户装完 Ubuntu 之后发现挣扎半天也无法把发行版转为 WSL2实际上就是因为缺了内核。如果你双击这个安装包提示This update only applies to machines with the Windows Subsystem for Linux先检查系统是不是真的 v2004再看安装包是不是 64 位版本。权限不够也会造成类似的提示右键以管理员身份运行往往就能解决。安装完成后可以打开 PowerShell 执行wsl --status能看到关于默认 WSL 版本的信息就说明内核部分已经就位了。3.4 设置默认版本并装好发行版接着在 PowerShell 里执行wsl --set-default-version 2这一句的意思是之后新安装的 Linux 发行版默认使用 WSL2 架构。接着去应用商店搜索并安装一个发行版。我选的是 Ubuntu 20.04 LTS一方面兼容性验证充分另一方面大多数 Docker 相关文档和命令都以 Debian/Ubuntu 系为例跟着操作不迷路。下载完成后首次启动需要设置用户名和密码这个用户名会自动成为 WSL 里的标准用户后续操作大部分都要用它配合 sudo 来执行。装完之后用下面命令确认架构版本wsl -l -v看到 VERSION 列是 2说明发行版已经跑在 WSL2 上了。如果显示 1就执行一次转换wsl --set-version Ubuntu-20.04 2转换过程可能需要几分钟中途不要关闭窗口也不要着急做其他操作。如果卡住不动回到第 2.2 节检查虚拟化开关。4. Docker部署的两条路线对比完我选了发行版直装4.1 Docker Desktop的WSL2后端体验在 Windows 上部署 Docker最省事的方法是安装 Docker Desktop然后在设置里启用 WSL 2 后端。启用之后Docker Desktop 可以直接接管 WSL2 里的 Docker 执行环境。在 Windows 侧的 PowerShell 里执行docker version能正常返回进入 WSL 发行版后同样可以执行docker命令两边用的是同一个守护进程体验上很统一。图形化面板可以直观查看镜像、容器、卷的状态还能在Resources - WSL Integration里选择具体要集成的发行版。这套方案适合 Windows 工作流很重的人毕竟图形界面确实直观。但它的代价是资源占用。Docker Desktop 作为 Windows 后台程序会常驻托盘图标一直挂着对内存紧张的老测试机来说有点奢侈。我在这台 8GB 的 win10 v2004 笔记本上试过开机后光是 Docker 相关进程就能吃掉不少内存再跑几个容器就开始吃力了。4.2 发行版内直接安装docker-ce的完整过程考虑到这台机器配置一般我最终选择了在 WSL2 发行版里直接安装 Docker。这样没有 Windows 侧的多余进程Docker 以一个 Linux 服务的形式在 WSL 内运行干净、轻量、可控。进入 WSL 终端按顺序执行sudo apt update sudo apt install -y docker.io docker-compose-v2 sudo usermod -aG docker $USERdocker.io是 Ubuntu 软件源里自带的 Docker 引擎包版本可能不是最新的但稳定够用。docker-compose-v2是新版 compose 插件后续跑多容器项目会用到。把当前用户加入docker组之后就可以不用每次都敲sudo docker。启动 Docker 服务sudo service docker start注意在 win10 v2004 这个时间点的 WSL2 默认不使用 systemd所以systemctl start docker这种命令很可能报错。用service docker start更可靠。每次重启 Windows 或者 WSL 之后都需要重新执行一次这条命令。验证是否正常docker run --rm hello-world如果能看到一段说明 Docker 工作正常的输出安装就完成了。第一次跑这个验证命令时会顺便拉取镜像如果一直停在拉取阶段可以先看看第 6.4 节的内容。4.3 两条路线的适用场景差异我整理了一个简单的对比方便你根据自己情况选择对比项Docker Desktop WSL2 后端WSL2 发行版内直装管理界面有图形界面直观无界面纯命令行资源占用较高Windows 侧常驻进程较低只在 WSL 内运行Docker 命令可用位置Windows 终端和 WSL 内都可主要在 WSL 终端内多容器编排自带 compose 支持需安装 docker-compose-v2适合场景日常开发、依赖图形化操作低配机器、服务器习惯、只想用 CLI没有绝对的好坏我最后选直装是因为这台测试机就是要长时间跑几个容器内存本来就不宽裕不想再让一个 Windows 侧的重型软件抢资源。如果你日常主要用 Windows 侧的 IDE 和终端觉得敲命令不如点鼠标方便那 Docker Desktop 更适合你。5. 跑起来之后绕不开的三件事端口、文件挂载、内存占用5.1 从Windows访问容器端口的转发机制WSL2 默认开启了 localhost 转发所以在 WSL2 里启动一个监听特定端口的服务Windows 浏览器直接访问localhost:端口就能打开。这个特性对 Docker 容器同样生效。比如在 WSL 里执行docker run -d -p 8080:80 nginxWindows 侧访问http://localhost:8080就能看到 nginx 默认页面。这个体验很舒服也是很多人觉得 WSL2Docker 好用的原因之一。但要注意这个 localhost 转发只对本机访问生效。如果想让局域网里其他设备通过 Windows 的 IP 访问这个容器直接访问往往不通。原因在于 WSL2 本身是一个 NAT 网络容器端口映射绑定在 WSL 内部的虚拟网卡上Windows 没有自动把外部的入站流量转发进去。这种情况我会用netsh interface portproxy手动转发具体做法在第 6.5 节详细展开。5.2 文件互通的性能陷阱与挂载建议WSL2 支持 Windows 和 Linux 两侧文件互通Windows 的磁盘在 WSL 里挂载在/mnt/c、/mnt/d之类的位置。但这个互通是能用和好用之间的差别。把项目代码放在 Windows 目录下然后用 Docker 挂载进容器这在很多教程里看起来很正常但实际跑起来会发现速度很难接受。大量小文件的读写比如前端项目的node_modules在/mnt/c下进行会比在 WSL 自身文件系统里慢好几倍。数据库容器如果直接把数据目录挂载到 Windows 目录IO 延迟会被明显放大。我的建议很简单所有需要容器频繁读写的目录都放在 WSL 的 Linux 文件系统内部比如/home/用户名/projects。Windows 和 Linux 文件互通只用来做少数文件交换而不是作为长期工作目录。如果某些工作流必须访问 Windows 路径可以挂载为只读降低权限问题和性能损耗docker run -d --mount typebind,src/mnt/c/shared,dst/data,readonly nginx这条命令里readonly就明确定义了容器内对该目录只能读不能写适合做素材分发。5.3 用.wslconfig限制vmmem的内存与核数第一次跑完 WSL2 之后打开任务管理器可能会看到vmmem进程占用了很高的内存。这个进程就是 WSL2 虚拟机本身。WSL2 默认可能拿走近一半可用物理内存在只有 8GB 的机器上会造成 Windows 侧明显卡顿。解决办法是在 Windows 用户目录下新建一个名为.wslconfig的文件写入工整的配置[wsl2] memory6GB processors4 swap2GB localhostForwardingtrue保存之后在 PowerShell 里执行wsl --shutdown再重新进入 WSL2配置就会生效。memory限制了 WSL2 能使用的最大内存processors限制了 CPU 核数swap是它在内存压力大时使用的交换空间。这样设定后vmmem的占用就不会再失控。我在测试机上给 WSL2 分配 6GBWindows 侧留 2GB跑两三个容器加一个数据库整体还能保持流畅。如果你需要同时跑很多服务可以根据实际使用情况调整数值但建议至少给 Windows 保留 2GB 内存避免系统界面失去响应。6. 实操过程记录的六个坑与完整排查链路6.1 内核更新包提示不适用第一次装的时候我下载了内核更新包双击结果弹出提示只适用于适用于 Linux 的 Windows 子系统。当时心里一紧以为是系统版本不对。后来逐个排查用winver确认系统确实是 v2004内部版本 19041。确认下载的是 x64 安装包而不是 ARM 版本。右键安装包选择以管理员身份运行。第三步解决问题。当时系统存在一种常见情况普通用户双击安装包时权限不足安装程序无法正确检测到 Windows 功能就会给出误导性的错误提示。有了这次经验后面我再遇到类似安装包报错第一反应都是先提权重试。6.2 wsl转换版本长时间卡顿在把 Ubuntu 从 WSL1 转为 WSL2 时wsl --set-version Ubuntu-20.04 2执行后一直停在正在进行转换十几分钟没有进展。我当时没有立即放弃而是先检查了任务管理器里的 CPU 虚拟化状态确认是已启用再去 PowerShell 里查看虚拟机平台功能状态结果也是 Enabled。看起来一切正常但转换就是不动。最后在社区看到类似案例有经验的人说这是功能启用后没有彻底重启导致的。虽然系统状态显示 Enabled但底层驱动没有真正加载。我执行了一次wsl --shutdown然后重启 Windows再次进入终端执行转换命令几分钟后就成功了。这个坑给我的教训是显示状态为启用不代表运行时已经生效遇到卡顿先从上到下检查一遍最基础的条件往往比盲目重试更有效率。6.3 容器启动时报iptables错误跑docker run hello-world时终端里出现过类似于iptables: No chain/target/match by that name的报错。Docker 在启动容器时要配置网络规则它会尝试修改 Linux 内核的 iptables 链如果内核模块或链的状态异常容器起不来。我尝试过的排查步骤是这样的先执行wsl --shutdown再重新进入这个操作可以重置 WSL2 虚拟机的内核状态。如果问题还在就查看 Docker 服务日志sudo service docker status或者直接看系统日志往往能看到更具体的错误原因。在这个问题上我最终靠重启 WSL2 解决了。如果你遇到的更顽固还有一种做法是重新安装对应的 WSL 发行版因为这种问题有时候和发行版镜像里预置的网络配置有关重装比深挖内核快得多。6.4 镜像拉取超时在 WSL2 里执行镜像拉取时遇到过长时间卡在 Pulling fs layer 的情况。这个问题在网络环境复杂时很常见。解决办法是给 Docker 配置一个可用的镜像加速地址。编辑或创建/etc/docker/daemon.json{ registry-mirrors: [https://docker.example.com] }把里面的地址替换成你所在网络环境实际可用的加速地址。修改之后重启 Dockersudo service docker restart再重新执行拉取操作。需要注意加速地址的有效性和速度会随时间变化如果发现某个地址变慢及时换掉就行。这个配置文件对 Docker Desktop 同样适用只是文件位置在 Windows 用户目录下 Docker 的设置里。6.5 局域网设备访问容器端口失败容器起来了本机能通过localhost:8080访问但手机或另一台电脑通过这台 Windows 的局域网 IP 访问同一端口却连接不上。排查时我先确认了容器在 WSL2 内部的 IPhostname -I假设输出是172.19.96.1然后发现 Windows 只是把本机 localhost 流量转给了 WSL2并没有转发局域网入站请求。于是用管理员 PowerShell 添加一条端口转发规则netsh interface portproxy add v4tov4 listenport8080 listenaddress0.0.0.0 connectport8080 connectaddress172.19.96.1同时放行 Windows 防火墙netsh advfirewall firewall add rule namedocker8080 dirin actionallow protocolTCP localport8080两条命令执行完之后局域网设备终于可以访问了。要注意 WSL2 每次重启后 IP 可能变化如果发现又访问不了检查一下 IP 是否变了然后更新 portproxy 规则。6.6 笔记本休眠唤醒后WSL2失联测试机经常被合上盖子带出门回来再打开盖子WSL2 里的 Docker 就经常连不上。出现cannot connect to the Docker daemon用wsl -l -v查看发行版状态往往显示 Stopped。WSL2 的虚拟机在 Windows 休眠后不会自动恢复所以发行版处于停止状态容器自然就没了。解决的思路很直接彻底重启 WSL2。在 PowerShell 里执行wsl --shutdown然后重新进入发行版sudo service docker start如果你希望这个过程更省事可以把这两条命令写进一个脚本每次唤醒后双击运行。不过我的个人建议是别让它长期后台常驻WSL2 本身就该按需启动频繁跑容器时再手动拉起来即可。最后说点个人体会。这套方案跑下来最大的感受是 win10 v2004 虽然已经是很早以前的版本但只要摸清楚 WSL2 的脾气日常开发完全够用。如果让我重来一次我会在装系统后第一时间检查虚拟化开关并且一开始就把项目目录放在 Linux 侧而不是等到被慢吞吞的挂载折磨一整天再去调整。另外发行版直装 Docker 和 Docker Desktop 并没有谁取代谁的关系Desktop 适合 Windows 工作流很重的人发行版直装更适合像我这样只需要一个稳定 Docker 环境的场景。希望这篇记录能帮你少走一点我走过的弯路。