
在Windows上折腾开发环境最让人上火的不是代码写不出来而是环境装不起来。以前我为了在本地跑Linux环境装过虚拟机、搞过双系统每次换来换去都觉得很别扭。直到把WSL 2和Docker Desktop这套组合彻底玩明白之后Windows下的开发体验才真正顺了。这篇文章不聊虚的就把我从零开始安装WSL子系统、配置Docker、日常使用以及踩坑排错的全过程写下来希望能让刚上手的同学少走弯路。无论你是做后端开发、运维还是经常要碰Redis、MySQL、Elasticsearch这些中间件只要日常主力机器是Windows这套方案都能让你的开发环境快速Linux化而且不污染主系统。下面所有命令我都亲自实测过按顺序操作基本就能一次跑通。1. WSL是什么为什么说它是Windows开发的标配1.1 WSL 1和WSL 2的区别以及我为什么推荐WSL 2WSL全称Windows Subsystem for Linux也就是Windows的Linux子系统。它不是一个虚拟机也不是一个模拟器而是微软在Windows内核里实现的一个兼容层WSL 1或者一个定制过的轻量虚拟机WSL 2。简单说它让你在Windows上能原生运行Linux命令行工具、脚本甚至是完整的Linux发行版而不用单独去装VMware或者VirtualBox。WSL 1和WSL 2最大的区别在于实现内核的方式。WSL 1走的是翻译层路线把Linux的系统调用翻译成Windows的系统调用好处是启动快、内存占用小但兼容性有硬伤很多依赖Linux内核特性的软件直接跑不动。WSL 2则干脆跑了一个经过微软深度定制的真正Linux内核只是把它封装在一个轻量虚拟机里因此兼容性大大提升Docker这类重度依赖内核能力的工具只能在WSL 2上正常工作。实际用下来WSL 2的启动速度依然很快冷启动也就一两秒日常开发完全感知不到后台有个轻量虚拟机在运行。我自己是强烈推荐直接上WSL 2的。除非你有极其特殊的老项目必须依赖WSL 1的文件系统行为否则新装环境一律选WSL 2这点在后面配置Docker的时候会体现得更明显因为Docker Desktop对WSL 2的集成是最完整的。1.2 什么场景适合WSL 2 Docker这套组合这套组合最典型的应用场景就是本地开发需要Linux环境。比如你要跑Redis、MySQL、Elasticsearch、GitLab这些中间件在Windows上直接装原生版本多多少少会有兼容问题很多老版本中间件在Windows上要么跑不起来要么有性能损耗。用WSL 2里的Docker来跑既能享受Linux环境的完整兼容性又不影响Windows主系统的干净整洁。我自己的习惯是宿主机只装必要的开发工具所有数据库和中间件全部用容器跑出问题直接重建容器完全不污染系统。但这套方案也不是万能的。如果你需要图形界面的Linux桌面或者需要大量直连USB设备、做嵌入式串口调试WSL 2用起来就比较别扭。CUDA开发虽然WSL 2现在也支持了但配置起来还是有门槛的不建议新手一上来就挑战。WSL 2适合的是命令行工作流而不是替代一台完整的Linux桌面机。需求判断清楚了再动手能省掉后面很多无用功。2. WSL安装全流程从环境检查到跑通Ubuntu2.1 安装前先检查这3件事第一件事确认Windows版本。WSL 2要求Windows 10版本号不低于2004build 19041或者直接用Windows 11。怎么查WinR输入winver回车看窗口里的版本号。如果你是Windows 10老版本我建议先把系统更新全部做完再继续省得到时候各种WSL命令报“当前版本不支持”的错误。第二件事确认CPU虚拟化是否开启。打开任务管理器切到“性能”标签页看左下角“虚拟化”那行是不是“已启用”。如果显示“已禁用”需要进BIOS开启Intel VT-xIntel平台或者SVM ModeAMD平台。这一步非常关键因为WSL 2本质上是虚拟机没有虚拟化支持根本起不来。我见过不少人的Docker Desktop报错追根溯源都是这一项没开。第三件事确认Windows功能组件完整。在“启用或关闭Windows功能”里找到“适用于Linux的Windows子系统”和“虚拟机平台”这两项确保都处于勾选状态。勾选之后需要重启系统才能生效。经常有朋友在这步漏掉“虚拟机平台”导致后面Docker Desktop启动一直报虚拟化相关错误这个问题我在第4节还会详细展开。2.2 使用wsl --install一键安装如果你的Windows版本比较新最快的方式就是管理员身份打开PowerShell直接运行wsl --install这条命令会自动完成三件事启用需要的Windows功能WSL和虚拟机平台、下载并安装默认的Linux发行版一般是Ubuntu、把默认WSL版本设置为2。整个过程如果网络状况好大概5到10分钟。装完之后系统会提示你设置Linux用户名和密码这个用户名跟Windows用户名可以不一样自己记住就行。如果想指定发行版可以先用下面这条命令看有哪些可选wsl --list --online然后安装你需要的版本比如wsl --install -d Ubuntu-22.04我个人一直用Ubuntu 22.04 LTSLTS版本维护周期长、踩坑资料多后面换源、装工具都方便。如果公司项目对系统版本有要求再考虑Debian、openSUSE这些安装方法一模一样。注意第一次进入Ubuntu时会让设置一个非root用户日常操作尽量用这个普通用户需要提权时用sudo不要所有事都用root养成好习惯能避免很多权限相关的坑。2.3 安装慢、下载卡住的经典解决方案这是被问得最多的问题没有之一。wsl --install或者wsl --update下载很慢甚至一直卡在某个进度不动。原因很简单安装包要从微软服务器下载部分地区到微软服务器的网络链路不稳定这是客观存在的现象不是你操作有问题。比较靠谱的解决办法有几个。第一个是用离线安装包去微软官网下载适用于x64的WSL 2内核更新包wsl_update_x64.msi手动安装完之后再运行wsl --set-default-version 2系统就不会再走那个慢吞吞的下载流程了。第二个方法是先把Windows系统更新全部打满有些所谓“下载慢”其实是因为系统组件不全更新完以后再重试wsl --install往往就正常了这个情况我在两台机器上都遇到过。另外一个小技巧如果机器之前装过WSL后来卸载过再装的时候经常遇到老配置残留的问题。这时候先运行wsl --shutdown再运行wsl --unregister 发行版名把旧环境清理干净然后重新安装能避免很多莫名其妙的报错。安装过程中不要去反复开关机让它自己跑完就行。3. WSL日常配置与使用技巧3.1 换源、更新与基础环境配置Ubuntu装好后第一件事永远是换源和更新。为什么换源因为apt默认用的是Ubuntu官方源访问速度上确实不稳定换成国内镜像源之后下载软件包的速度能快好几倍。操作很简单先备份原来的源列表sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak然后把sources.list里的地址替换成镜像地址。以Ubuntu 22.04为例我一般直接用编辑器打开文件把archive.ubuntu.com整体替换成mirrors.aliyun.com也可以顺手把security.ubuntu.com一起替换掉。改完以后执行sudo apt update sudo apt upgrade -y这里提一句apt upgrade升级过程中如果看到linux-image相关的包更新不用慌WSL 2用的是微软单独提供的Linux内核这些apt包一般不会被实际加载不会把WSL搞坏。基础环境里还有两样东西是必备的build-essential和git。前者是编译工具链装各种需要源码编译的工具时离不开后者是日常开发的基本工具不解释了。sudo apt install -y build-essential git顺便把locale也检查一下如果发现中文显示问号或者乱码装个中文字体就能解决sudo apt install -y fonts-noto-cjk3.2 Windows和WSL之间文件互访文件互访是WSL使用中非常高频的操作。WSL 2里访问Windows的文件系统路径是/mnt/c、/mnt/d这样的格式比如C盘根目录就是/mnt/c。反过来从Windows里访问WSL的文件在资源管理器地址栏输入\wsl$\或者\wsl.localhost\就能看到你的WSL发行版目录可以直接像普通文件夹一样拖拽文件。这里有一个性能上的坑必须提醒跨文件系统读写性能很差。如果你的项目代码放在Windows文件系统比如D:\projects\demo然后在WSL里编译运行文件操作会慢到让人怀疑人生。为什么因为/mnt/c这种访问方式本质上是9P协议在Windows和Linux之间做文件转发每次读写都有额外损耗。正确的做法是把项目代码放在WSL自己的文件系统里也就是~/projects这类位置然后在Windows的资源管理器里通过\wsl$路径去访问和编辑。这样Windows侧用VS Code打开的是同一个文件WSL侧编译运行也是本地速度两侧体验都不差。如果你希望WSL默认不要自动挂载Windows盘可以在/etc/wsl.conf里配置[automount] enabled false改完运行wsl --shutdown再重新进入WSL就生效。3.3 在VS Code里连接WSL写代码这是WSL体验里最舒服的一环。在Windows上安装VS Code再安装微软官方的“WSL”扩展然后在WSL终端里进入你的项目目录运行code .VS Code会自动以远程模式连接到WSL打开项目文件夹。左边看到的文件树、终端、调试器全都是WSL里的但界面还是在Windows上体验和本地开发几乎没区别。这个模式叫Remote Development微软官方出品实测下来很顺手我日常写Go和Python项目都靠它。为什么要这么干因为这样你的编辑器和终端访问的是同一套文件系统代码编辑在Windows侧编译运行在Linux侧避免了两边文件不同步、权限不一致的问题。我在这套模式下连续工作大半年几乎没有遇到卡顿或断连。如果你第一次运行code .没反应先确认VS Code里装的是“WSL”扩展而不是“Remote - SSH”这两个容易混淆。3.4 多个发行版管理与默认版本切换WSL支持同时装多个发行版。装第二个发行版和第一个一样wsl --install -d Debian就能装Debian。查看当前所有发行版的状态wsl --list --verbose输出里会显示每个发行版的名称、状态和WSL版本比如Ubuntu-22.04显示为2。如果你希望所有新装的发行版默认使用WSL 2运行wsl --set-default-version 2如果想切换某个发行版的WSL版本wsl --set-version Ubuntu-22.04 2注意从WSL 1切到WSL 2需要一次转换过程耗时取决于发行版文件大小期间不要关机。反过来从2切到1也支持但一般没人这么干。默认进入哪个发行版也可以设置用wsl --set-default Ubuntu-22.04指定这样直接敲wsl命令就进到你想用的系统里。4. Docker Desktop的安装与WSL 2集成4.1 Docker Desktop下载与安装要点Docker Desktop是Docker官方为Windows和macOS推出的桌面版工具内置了Docker引擎、CLI、Compose以及图形化管理界面。对绝大多数人来说直接在Windows上用Docker Desktop是最省心的选择不用自己手动去装Docker Engine。下载直接从Docker官网下载Docker Desktop for Windows的安装包。安装时有两个关键选项要注意一是“Use WSL 2 instead of Hyper-V”这个复选框必须勾选这是Docker和WSL 2集成的开关二是安装过程中可能需要启用Windows相关功能按提示操作并重启即可。安装完以后第一次启动Docker Desktop会显示接受服务条款的界面同意之后它会自动检查WSL 2环境。如果一切正常右下角托盘会出现一只小鲸鱼图标。打开终端运行docker version能正常显示Client和Server两段版本信息就说明装好了。注意Server部分必须能显示出来如果只有Client信息说明Docker引擎没起来后面第6节我会专门讲排查思路。4.2 配置WSL集成与镜像加速Docker Desktop默认会集成默认的WSL发行版但如果你有多个发行版可以在Docker Desktop的Settings - Resources - WSL Integration里勾选你希望使用Docker的发行版。勾选之后在这个发行版的终端里直接就能用docker命令不需要任何额外配置。我几乎天天用这个功能在WSL里跑容器日志格式和文件路径都是Linux风格比在PowerShell里操作舒服太多。镜像加速这个事必须单独说一句。默认情况下Docker Hub的拉取速度在部分地区确实很慢拉一个几十兆的镜像要等半天。解决办法是在Docker Desktop的Settings - Docker Engine里配置daemon.json加入镜像加速器地址比如阿里云的容器镜像服务地址需要登录阿里云控制台获取专属地址或者中科大等公共镜像地址。改完点击Apply Restart让Docker重启生效。配置好的daemon.json大概长这样{ registry-mirrors: [ https://你的专属加速地址.mirror.aliyuncs.com, https://docker.mirrors.ustc.edu.cn ] }重点是这里说的是合法的容器镜像加速配置跟任何网络代理都没有关系。配好之后再来拉镜像速度会有肉眼可见的提升尤其拉mysql、redis这种常用镜像时体感特别明显。4.3 虚拟化报错的排查思路Docker Desktop启动时最常见的报错就是Docker Desktop failed to start because virtualisation support wasnt detected.这句报错的意思是检测不到虚拟化支持。排查思路从下往上走分三步。第一步确认BIOS里的虚拟化开关。开机进BIOS找到Intel Virtualization TechnologyIntel VT-x或者SVM ModeAMD设为Enabled。不同主板菜单位置不一样但关键词基本就是Virtualization、VT-x、SVM这些。改完保存重启。第二步确认Windows的虚拟化平台功能完整。用管理员身份运行PowerShell执行systeminfo看输出里“Hyper-V 要求”部分检查“已在固件中启用虚拟化”是不是“是”。如果这里显示“否”基本还是BIOS的问题如果显示“是”但Docker依然报错那就是Windows功能没开全。去“启用或关闭Windows功能”里打开“虚拟机平台”和“Hyper-V”重启。第三步检查安全软件和系统设置。某些安全软件会关闭虚拟化相关的系统服务这个不多见但我遇到过。另外Windows的“内核隔离”功能在部分旧配置机器上会导致Docker无法检测虚拟化可以去“Windows安全中心 - 设备安全性 - 内核隔离”里尝试关闭内存完整性然后重启再试。这个开关平时不影响正常使用但确实能解决一部分Docker启动问题。5. 跑通第一个容器MySQL与Redis实战5.1 用Docker安装MySQL 8.0含数据持久化到了最实用的环节。装好Docker之后第一件事很多朋友的诉求就是跑数据库。以MySQL 8.0为例一条命令就能跑起来docker run --name mysql8 -p 3306:3306 -e MYSQL_ROOT_PASSWORD你的密码 -d mysql:8.0参数解释一下--name给容器起名字-p把容器的3306端口映射到宿主机的3306端口-e传环境变量这里设置了root密码-d表示后台运行mysql:8.0是镜像名加标签。但是这种最简单的跑法有个致命问题数据存在容器内部一旦容器删除数据全部丢光。生产环境绝对不能这么干本地开发我也不建议养成这个坏习惯。正确的做法是把MySQL的数据目录挂载到宿主机同时指定字符集docker run --name mysql8 \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORD你的密码 \ -v /home/你的用户名/mysql-data:/var/lib/mysql \ -d mysql:8.0 \ --character-set-serverutf8mb4 \ --collation-serverutf8mb4_unicode_ci-v参数把容器内的/var/lib/mysql映射到WSL里的/home/你的用户名/mysql-data。这样无论容器怎么删、怎么重建数据都好好地留在宿主机目录里。字符集参数指定utf8mb4是常规操作处理中文和特殊符号都不会出现乱码。启动以后在WSL终端里就能连上MySQLdocker exec -it mysql8 mysql -uroot -p输密码进入MySQL命令行执行show databases;能看到系统数据库就说明成功了。用第三方图形工具连接也轻松连接地址写localhost端口3306用户名root密码就是刚才设置的那个。5.2 用Docker安装Redis并配置主从Redis部分单机版一条命令docker run --name redis -p 6379:6379 -d redis:7Redis默认镜像不带配置文件如果要开启AOF持久化加--appendonly yes参数docker run --name redis -p 6379:6379 -d redis:7 redis-server --appendonly yes主从架构在本地做也很方便。先起一个主节点再起一个从节点让从节点通过--replicaof参数指向主节点。这里有个关键点容器之间通信不能用localhost得用容器的IP或者通过Docker网络。最省事的做法是创建一个Docker网络让两个容器加入同一个网络这样它们就能用容器名互相访问了docker network create redis-net docker run --name redis-master --network redis-net -p 6379:6379 -d redis:7 redis-server --appendonly yes docker run --name redis-slave --network redis-net -p 6380:6379 -d redis:7 redis-server --replicaof redis-master 6379验证主从是否生效进主库看一眼docker exec -it redis-master redis-cli info replication输出里role:master并且connected_slaves:1就说明从库连接成功。这种容器网络配法比手动查IP硬配靠谱得多因为容器重启后IP可能会变但容器名是不变的只要网络不删这种解析就一直有效。5.3 常用命令速查表整理一份我每天都会用到的Docker命令速查表新手可以直接抄命令作用docker ps -a查看所有容器包括已停止的docker images查看本地镜像列表docker logs -f 容器名实时查看容器日志docker exec -it 容器名 bash进入容器内部docker restart 容器名重启容器docker stop / start 容器名停止/启动容器docker rm 容器名删除容器docker rmi 镜像名删除镜像docker network ls查看Docker网络这些命令敲熟之后日常大部分操作就够用了。更复杂的编排需求比如同时起MySQL、Redis、Elasticsearch多个容器建议直接写docker-compose.yml然后用docker compose up -d一次性启动比一条条命令敲省心太多。一个同时包含MySQL和Redis的compose示例大概长这样version: 3.8 services: mysql8: image: mysql:8.0 container_name: mysql8 ports: - 3306:3306 environment: MYSQL_ROOT_PASSWORD: yourpassword TZ: Asia/Shanghai volumes: - ./mysql-data:/var/lib/mysql command: - --character-set-serverutf8mb4 - --collation-serverutf8mb4_unicode_ci redis: image: redis:7 container_name: redis ports: - 6379:6379 command: redis-server --appendonly yes volumes: - ./redis-data:/data在文件同目录下运行docker compose up -d两个服务就一起起来了日志统一管理。以后想停就docker compose down数据因为挂载了volume都留在宿主机。这才是正经的开发环境容器化用法推荐早早上手。6. 高频问题排查实录6.1 WSL版本过旧启动WSL或者VS Code连接WSL时经常弹出这样一段提示Your version of Windows Subsystem for Linux (WSL) is too old. Run wsl --update or update Windows to the latest version.这段报错的意思是WSL组件版本太老。解决办法很直接管理员PowerShell下运行wsl --update这个命令会把WSL更新到最新版本。如果wsl --update下载很慢或者失败跟前面第2节说的一样去微软官网手动下载最新的WSL更新包MSI格式安装再回到系统里执行wsl --version验证版本号。更新完以后之前的报错提示基本就消失了。这里有一个容易被忽略的点wsl --update更新的是WSL核心组件跟发行版内部的apt update是两码事。如果你只是想升级Ubuntu里的软件包需要进到WSL里跑apt update apt upgrade不要把两条命令混为一谈。6.2 Docker Desktop启动失败Docker Desktop启动失败的原因五花八门除了前面说的虚拟化检测不到还有几种高频情况。第一种是“WSL 2 installation is incomplete”。这种情况通常出现在你装了WSL但内核没更新到最新。先运行wsl --update然后在PowerShell里运行wsl --set-default-version 2确认默认版本再重启Docker Desktop。第二种是Docker引擎起来之后又立刻退出。直接打开Windows事件查看器找到Docker相关的错误日志排查效率会高很多。我遇到过一次是Windows防火墙规则冲突把Docker Desktop在防火墙里的入站规则删掉重启软件就恢复了。第三种是端口被占用。容器映射端口时跟Windows其他服务冲突比如Windows的World Wide Web Publishing Service默认占用80端口你要跑Nginx容器映射80就会失败。解决办法要么关闭占用端口的服务要么把容器映射改成8080这类端口业务上通常不会有影响。6.3 WSL占用内存过多WSL 2默认最多可以使用宿主机一半的内存如果你的机器是16G内存WSL可能分走8G这在只跑几个小容器的情况下其实是浪费。解决方法是在Windows用户目录下创建一个.wslconfig文件注意文件名带点写入[wsl2] memory4GB swap2GB processors2memory限制WSL最大使用内存swap给虚拟内存大小processors限制CPU核心数。改完保存运行wsl --shutdown让配置生效。这样WSL就不会无限吃资源了尤其开着Docker Desktop挂多个容器的时候内存分配会更从容。文件里还可以配置localhostForwarding等参数默认就是开的一般不需要动。6.4 容器端口无法访问在WSL里启动了一个容器映射了3306端口然后从Windows本机连localhost:3306提示连不上。这个问题的排查路径一般是这样。先确认容器状态docker ps看容器是不是在运行。再进容器里确认服务真的起来了docker exec -it 容器名 bash然后在容器内部测一下端口。如果容器内部正常那就是端口映射的问题检查docker run时的-p参数是不是写错了。还有一种特殊情况是Windows防火墙拦截了WSL的端口转发。WSL 2默认会把Windows的localhost转发到WSL里的容器但某些系统更新或者安全软件会破坏这个转发链路。遇到这种情况在管理员PowerShell里执行netsh interface portproxy reset然后重启WSL。一般就能恢复localhost转发。如果还是不行干脆在Windows里直接用WSL的IP加端口访问。先在WSL里运行ip addr查IP然后在Windows浏览器里访问这个IP加端口能通的话就说明Docker和容器本身没问题问题就出在localhost转发这条链路上往这个方向排查就不会跑偏。6.5 其他高频问题速查把平时被问到的几个小问题也一并列出来问题解决方案wsl命令不存在系统太老或WSL组件未安装先补Windows更新再wsl --installUbuntu里中文乱码sudo apt install fonts-noto-cjk必要时配置locale容器时区不对docker run时加-e TZAsia/ShanghaiDocker镜像拉取超时检查daemon.json里的镜像加速地址是否可用VS Code连不上WSLwsl --shutdown重启WSL再重开VS Codedocker compose命令找不到确认Docker Desktop已升级到较新版本旧版用docker-compose最后再分享一个我的个人习惯我会在WSL用户目录下的.bashrc文件末尾加几个常用别名比如dcdocker compose、dpsdocker ps、dlogsdocker logs -f这样敲命令能省不少时间。配置这种事情没有绝对标准关键是自己用得顺手但一定要记得改完配置文件后执行source ~/.bashrc让别名立即生效不然容易以为自己没改对。工具链这种东西光看文档是记不住的只有自己亲手从零搭一遍、踩一遍坑才能真正建立起体系化的认识。我在这个过程里最深刻的体会是大部分报错其实不是环境不行而是某个前置条件没满足比如虚拟化没开、WSL版本太老、端口被占用。按顺序逐层排查绝大多数问题十分钟内都能定位。希望这篇东西能帮你在Windows上把WSL和Docker这套环境一次跑通。