1. Windows上跑Docker的路线之争:为什么绕不开WSL 2
作为一个常年混迹在Windows笔记本上的开发者,我前前后后把Docker的安装方案折腾了个遍。早年用VirtualBox,后来试过Hyper-V,再后来在Win10上装了Docker Toolbox,直到WSL 2真正成熟之后,我才彻底安定下来。如果你现在问我“Windows下到底怎么装Docker最舒服”,我的答案非常简单粗暴:先装好WSL 2,再决定是走Docker Desktop还是直接在WSL里装Docker Engine——但无论如何,WSL 2都是那个绕不开的底座。
为什么这么说?因为WSL 2不是简单的“Linux兼容层”,它是微软用真正的Linux内核跑起来的轻量虚拟机。WSL 1是通过系统调用翻译的方式模拟Linux环境,很多场景下会有兼容性问题,尤其是Docker这种重度依赖内核特性的软件。而WSL 2直接提供了一个完整的、经过微软定制和优化的Linux内核,这意味着你在WSL 2里跑的Docker容器,和在真Linux服务器上跑的几乎没有本质区别。容器依赖的cgroup、namespace、overlayfs这些内核机制都是货真价实存在的,所以Docker在WSL 2里不会出现“work on my machine但在这里挂掉”的尴尬。
从架构上看,如果你选择Docker Desktop,它会在安装时检测到WSL 2,然后创建一个名为docker-desktop的专用WSL发行版,所有容器的执行都发生在那个发行版里。如果你选择在WSL的Ubuntu发行版里原生装Docker Engine,那更直接——Docker守护进程就跑在你自己的Ubuntu里,完全由你自己控制。
我见过太多人在这一步犯了选择困难症。有人觉得Docker Desktop太“重”,有人觉得命令行装Engine太“裸”。其实这两条路各有各的适用场景,我后面会用一整章来对比。但不管走哪条路,前提都是先把WSL 2这个地基打牢。这篇文章就顺着这条主线,从WSL 2的安装、避坑,到两条Docker路线的详细操作,再到镜像加速、MySQL和Redis的落地实战,一次性把这些东西讲透。
2. 装WSL 2先跨过三道坎:版本、虚拟化和内核
2.1 版本要求比你想的更严格
很多人在安装WSL 2时遇到的第一个问题,根本不是命令不会敲,而是Windows版本不支持。WSL 2要求Windows 10版本在2004及以上,或者Windows 11。如果你是Win10且版本比较旧,直接运行wsl --install会提示你需要更新系统,甚至可能直接报错。
这里有个很容易忽略的小细节:wsl --install这个命令虽然在较新的Windows上已经是一键搞定(默认装Ubuntu),但在版本不满足的情况下,你连这个命令都用不了。我自己就见过一台Windows 10 1909的机器,运行wsl --install直接提示“命令行选项无效”。解决办法只有一个:更新Windows系统到至少2004版本,或者升级到Windows 11。
还有一个相关的高频报错是wsl --update 403。这个我遇到过一次,本质是Windows Update的组件在下载WSL内核更新包时网络异常,或者系统对更新服务的策略限制。解决办法是手动下载WSL 2内核更新包安装,或者直接使用wsl --update --web-download参数绕过Windows Update链路。我在Win11上测试下来,--web-download这个参数非常管用,它直接从微软官网下载,而不是走Windows Update的通道,少了很多折腾。
2.2 虚拟化没开,一切白搭
装完WSL 2之后,很多人第一次运行wsl会卡在启动阶段,或者Docker Desktop直接弹窗报错virtualization support not detected。这个报错几乎所有Windows Docker用户都见过,字面意思是“没有检测到虚拟化支持”,但它实际对应的原因通常有三个:
第一个是BIOS/UEFI里的虚拟化技术没开启。Intel平台是VT-x,AMD平台是AMD-V,如果你在主板的CPU设置里把这项关掉了,那WSL 2的虚拟机就跑不起来。这个要去BIOS里找,品牌机通常叫“Intel Virtualization Technology”或者“SVM Mode”,改成Enabled保存重启。
第二个是Windows的“虚拟机平台”功能没有启用。注意,WSL 2需要的是“虚拟机平台”这个可选功能,而不是“Hyper-V”。很多人分不清。在PowerShell里运行Get-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform可以看到状态,如果没有启用,需要以管理员身份运行:
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart然后重启。
第三个原因是你在同一台机器上同时用了第三方的虚拟化软件,比如旧版本VirtualBox或者VMware,它们和WSL 2的Hypervisor层冲突。这个相对少见,但如果前两项都没问题,还是报这个错,就需要检查一下是否有这种软件在占用虚拟化资源。
2.3 wsl --install 太慢时的离线自救方案
“wsl --install 太慢”是热搜词里非常扎眼的一个。这个命令看起来是一键装好,其实背后要做的事情很多:启用功能、下载WSL内核、下载并解压一个Ubuntu发行版镜像。如果你的网络环境比较一般,卡在“正在下载Ubuntu”这一步十几分钟甚至几个小时都很正常。
我推荐的离线方案是绕开wsl --install,手动安装:
第一步,手动启用两个Windows功能(前面给的dism命令,或者用控制面板里的“启用或关闭Windows功能”,勾选“适用于Linux的Windows子系统”和“虚拟机平台”)。
第二步,下载WSL 2内核更新包并安装,下载地址在微软官方文档里可以找到,是一个msi文件,下载后双击安装即可。顺便提一句,这个内核更新包其实就是个安装工具,装完后它会把真正的内核文件放到系统目录里,版本定了之后就不会像普通软件那样乱更新,所以哪怕Windows Update偶尔抽风也不影响。
第三步,绕过应用商店,直接用发行版安装包。cloud-images.ubuntu.com上有WSL专用的Ubuntu rootfs tar包,链接形如https://cloud-images.ubuntu.com/wsl/jammy/current/ubuntu-jammy-wsl-amd64-wsl.rootfs.tar.gz。下载后执行:
wsl --import Ubuntu-Docker C:\wsl\Ubuntu-Docker .\ubuntu-jammy-wsl-amd64-wsl.rootfs.tar.gzwsl --import这个命令会把rootfs作为一个新的WSL发行版导入,第二个参数是VHDX文件存放的目录,第三个参数是rootfs包的路径。导入完成后,用wsl -d Ubuntu-Docker进入即可。这个方法最大的好处是彻底绕开了应用商店和wsl --install的一键流程,网络负担极小,而且目录是自己指定的,方便管理。
顺带解决一个热搜词:“win11 wsl下载目录”。默认情况下wsl --install装出来的发行版数据存放在C:\Users\你的用户名\AppData\Local\Packages\下面,不同发行版对应的目录名不同。如果想迁移到其他盘,用wsl --export和wsl --import组合操作即可。我个人的习惯是一开始就用--import指定目录,省得以后迁移。
3. 选Docker Desktop还是WSL内Docker Engine:一份清醒的对比
3.1 两条路线的本质区别
先说一个关键结论:Docker Desktop在Windows上并不是直接跑在Windows内核里的。你装上Docker Desktop之后,它默认会启用WSL 2后端,然后创建两个WSL发行版,一个叫docker-desktop,一个叫docker-desktop-data。前者负责运行Docker守护进程和容器,后者负责存放镜像和数据。
也就是说,无论你是用Docker Desktop还是直接在WSL里装Docker Engine,真正干活儿的其实都是WSL 2里的Linux环境。Docker Desktop扮演的角色,更像是一个图形化管理器外加系统托盘守护程序;而你在WSL里用apt安装的dockerd,才是纯粹的那个Docker守护进程。
知道这一点后,对比就清晰了:
| 对比项 | Docker Desktop | WSL 2内Docker Engine |
|---|---|---|
| 安装难度 | 下载安装包点下一步,较省心 | apt命令几条,但需要手动配systemd |
| 资源占用 | 较高,后台常驻UI和多个进程 | 较低,只有dockerd和containerd |
| 图形界面 | 有Dashboard,可看容器/镜像/日志 | 无,全靠命令行 |
| 文件共享 | 跨WSL发行版文件共享顺手 | 需要自己配置挂载 |
| Kubernetes | 内置单节点K8s | 没有,需自行安装 |
| 适合场景 | 新手、需要可视化、需要K8s | 命令行习惯、追求轻量、开发环境 |
3.2 Docker Desktop:适合谁,有哪些代价
如果你之前完全没接触过Docker,第一次用就想把容器、镜像、卷这些概念搞明白,Docker Desktop的Dashboard确实帮了大忙。你能直观地看到哪些容器在跑、日志长什么样、端口映射关系,甚至可以在界面上直接启停容器。对于需要使用Kubernetes做本地开发的人来说,Docker Desktop内置的单节点K8s也很实用,免去了自己用minikube或kind折腾的麻烦。
但代价也很明显。Docker Desktop占用内存比较大,默认配置下它会分走好几个GB的RAM。如果你的笔记本只有16GB内存,同时跑着IDE、浏览器、一堆容器,很容易感觉卡顿。另一个烦人的点是它会常驻一个系统托盘程序,时不时弹个广告让你升级到Pro版本——虽然它现在对个人和小公司是免费的,但那种“被推销”的感觉怎么都不太舒服。
3.3 WSL内Docker Engine:适合谁,缺什么
如果你日常的操作习惯是全键盘流,容器管理用docker ps和docker logs就够了,那我强烈建议直接在WSL的Ubuntu发行版里装Docker Engine。它不装任何多余的图形组件,就是一个干净的服务,开机由systemd拉起来,命令行直接控制。
代价是你需要自己处理一些“原本Docker Desktop帮你处理好的事情”。比如跨发行版的文件共享没有开箱即用的方案,比如你在Ubuntu里跑容器,想访问Windows的C:\code目录,要自己挂载/mnt/c,而且性能很差(这个我后面会讲)。再比如没有K8s,想在本地模拟集群环境得额外装kind或者k3s。这些对老手来说不是问题,但如果你刚入门,可能会觉得处处是坑。
我的个人意见是:如果你有Windows下的图形化桌面需求,或者想快速体验K8s,选Docker Desktop;如果你只是想在Windows上有一个可用的Docker环境来跑中间件开发测试,直接在WSL里装Engine,干净利落。
4. 在WSL 2里原生安装Docker Engine的完整过程
4.1 准备一个干净的Ubuntu发行版
我推荐用Ubuntu 22.04或24.04作为底座。这里有个小经验:如果你用wsl --install -d ubuntu-24.04安装,第一次进入的时候会要求创建一个UNIX账号(即热搜里的“wsl create a default unix account”),这个账号默认归属于sudo组,而root用户默认锁定,日常操作就靠这个账号。如果用wsl --import导入rootfs包,默认进去是root用户,没有普通账号,需要自己创建。
为了避免权限管理上的混乱,我建议在开发区分一个非root用户:
adduser dev usermod -aG sudo dev然后通过修改/etc/wsl.conf设置默认用户:
[user] default=dev在Windows里执行wsl --shutdown,重新进入后就会以dev身份登录。
要启用systemd也很简单。WSL 2较新版本支持在/etc/wsl.conf里开启systemd:
[boot] systemd=true保存后wsl --shutdown再重启,systemctl status就能正常工作。这一步对后面安装Docker Engine非常关键,因为Docker服务需要systemd来托管,虽说不开systemd也能手动启动dockerd,但管理起来会很别扭。
4.2 选择安装源:官方源、脚本还是镜像源
WSL里装Docker Engine有三种常见方式,我逐一对比一下:
官方apt源。按照Docker官方文档执行,先安装依赖包,添加Docker的GPG key和apt仓库,再
apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin。这是最权威的方式,缺点是如果你所在网络访问Docker官方源不稳定,apt update时会卡住。get.docker.com一键脚本。
curl -fsSL https://get.docker.com | sh,这个脚本实际上还是走了官方源,只不过省去了手动配仓库的步骤。网络好的时候最快,网络不好就一起卡。清华镜像源或阿里镜像源。把Docker的apt仓库地址替换成国内镜像,下载速度非常可观。国内开发者我一般都推荐这种方式。
以清华源为例,配置方式是:
sudo apt-get update sudo apt-get install ca-certificates curl sudo install -m 0755 -d /etc/apt/keyrings sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc sudo chmod a+r /etc/apt/keyrings/docker.asc echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu \ $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt-get update sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin特别注意一点:download.docker.com和mirrors.tuna.tsinghua.edu.cn/docker-ce是两回事,前者是GPG key的下载地址,这个通常能访问;后者是实际软件包的镜像仓库。如果gpg下载也慢,可以把keyring这一步也换成国内镜像,不过我用下来一般没问题。
4.3 启动服务、免sudo、配置开机自启
装完Docker Engine之后,第一件事是把服务跑起来:
sudo systemctl enable docker sudo systemctl start docker如果你刚才没开systemd,这里会提示System has not been booted with systemd as init system,那就只能手动用sudo service docker start或者直接sudo dockerd &。所以再次强调,先把systemd开好,一劳永逸。
然后你一定会遇到的问题就是每次敲docker命令都要加sudo。解决办法是把当前用户加入docker用户组:
sudo usermod -aG docker $USER退出当前终端再重新进,docker ps就不需要sudo了。这个操作比在每次命令前面加sudo或者给docker二进制加setuid安全得多,docker组只对该组成员放开访问权限,没有直接提升到root。
验证一下环境是否正常:
docker version docker run hello-worlddocker run hello-world是我验证Docker守护进程最常用的方法。它能运行说明pull镜像、创建容器、运行指令这条链路都通了。
4.4 一条命令都没出错?别高兴太早,看看这几个配置
在我实际使用中,有几个配置不改的话,后面总会恶心你一下。
第一个是Docker数据根目录。WSL的VHDX默认在C盘,如果你像上面那样用wsl --import时指定了其他盘,那VHDX就在你指定的目录里,不用担心。但如果默认安装在C盘,装了一堆镜像之后C盘空间吃紧,要迁移就麻烦。建议在/etc/docker/daemon.json里指定data-root:
{ "data-root": "/mnt/wsl/docker-data" }注意别把data-root放到/mnt/c下面,那样性能会非常差。WSL有自己的虚拟磁盘,放在Linux文件系统里才是正路。
第二个是DNS配置。WSL 2的/etc/resolv.conf默认是自动生成的,如果公司网络有内网DNS,可能容器内域名解析会出问题。可以在/etc/wsl.conf里加一行[network] generateResolvConf = false,然后自己维护resolv.conf。
5. 镜像拉不动的根源与MySQL、Redis落地实战
5.1 镜像下载慢的根源:Docker Hub的连通性
装好Docker Engine只是第一步,真正用起来之后,你很快会被docker pull折磨。默认情况下,Docker会从Docker Hub拉取镜像,而国内网络访问这个公共仓库的速度很不稳定,一个几百MB的镜像可能要下半小时,还经常中断。
Docker在设计上预留了镜像加速机制,就是配置registry mirror。你可以在/etc/docker/daemon.json里加:
{ "registry-mirrors": ["https://docker.m.daocloud.io", "https://dockerproxy.com"] }然后重启docker:
sudo systemctl daemon-reload sudo systemctl restart docker这里提醒一个细节:registry mirror实际上只对从Docker Hub拉取的官方镜像生效,比如mysql:8.0这种写全了镜像名的。有些镜像是从第三方仓库拉取的,比如gcr.io开头的,配mirror是救不了的,得单独给那个仓库做处理。
另外说句实话,现在网上的公共mirror时好时坏,速度不稳定是常态。如果公司有可用的镜像仓库,优先把公司私有仓库地址配上;如果实在拉不动大镜像,做好断点续传的心理准备——Docker pull本身支持多线程分层拉取,但断网重来依然是个老大难问题。
5.2 实际场景一:安装MySQL 8.0并连上宿主机工具
跑一个MySQL 8.0容器是我测试WSL 2环境时最常做的事。一条命令拉起来:
docker run -d \ --name mysql8 \ -p 3306:3306 \ -e MYSQL_ROOT_PASSWORD=root123 \ -e TZ=Asia/Shanghai \ -v mysql-data:/var/lib/mysql \ mysql:8.0 --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci这条命令里几个参数值得解释一下:
-p 3306:3306:把容器里的3306端口映射到WSL发行版的3306端口。注意,从Windows访问时,WSL 2会自动把localhost流量转发到WSL虚拟机里,所以Windows上的Navicat直接连localhost:3306就能通,不需要知道WSL的IP。但这里有一个常见的坑:WSL 2的IP是动态分配的,如果你在另一台机器要访问这个MySQL,不能用同一个IP,要么用localhost这种转发,要么用端口转发工具。局域网访问建议直接Windows下做端口转发,或者在Windows上装个Docker Desktop管道过来,总之别直接在WSL里监听所有端口然后指望外部访问。-e MYSQL_ROOT_PASSWORD=root123:指定root密码。直接写在命令里方便,但如果只是测试环境;生产环境建议用env文件传,避免密码出现在shell历史里。-v mysql-data:/var/lib/mysql:数据卷持久化,这样删掉容器重建数据还在。最后的
--character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci是MySQL的启动参数,不是Docker参数,它会被透传给mysqld进程。
启动后用docker logs mysql8看初始化日志,看到ready for connections就说明成功了。想验证字符集设置是否生效,直接:
docker exec -it mysql8 mysql -uroot -proot123 -e "SHOW VARIABLES LIKE 'character_set_server';"5.3 实际场景二:Redis主从集群的快速搭建
在WSL里搭Redis主从是我最推荐的练手场景,因为这能让你理解Docker网络和容器的互联性。首先创建一个自定义网络,让容器之间可以通过容器名互访:
docker network create redis-net然后启动master节点:
docker run -d --name redis-master \ --network redis-net \ -p 6379:6379 \ redis:7 redis-server --appendonly yes再启动两个slave节点:
docker run -d --name redis-slave1 \ --network redis-net \ redis:7 redis-server --slaveof redis-master 6379 docker run -d --name redis-slave2 \ --network redis-net \ redis:7 redis-server --slaveof redis-master 6379注意:从Redis 5开始,默认配置用的是replicaof,而--slaveof这个命令行参数依然保留着兼容性,用起来没问题,只是在配置文件的语境里推荐用replicaof。两个slave容器没有-p参数是因为它们不需要对外暴露端口,只需要在redis-net网络内部被同网络的master访问即可。
验证主从状态:
docker exec -it redis-master redis-cli info replication输出的connected_slaves:2就说明主从关系建立成功了。这个过程中我踩过的一个小坑是:如果master先启动,slave后启动,两个slave之间可能会互相认为对方是主节点,造成主从循环。解决办法是确保master容器唯一,slave启动命令里明确指向redis-master别名即可。
5.4 场景落地时的通用避坑清单
无论跑什么容器,几个常见问题反复出现:
第一,容器时区默认UTC。如果日志时间总是差8小时,一定要在启动时加-e TZ=Asia/Shanghai,很多官方镜像的默认时区不带本地化配置。
第二,容器内rootfs是精简的,可能没有vim、ping、curl这些工具。排查网络问题的时候,docker exec -it <容器> bash进去却发现没有curl,会非常烦躁。建议提前在镜像里装好必要的调试工具,或者直接用docker run -it --rm redis:7 redis-cli这种方式来省去一层shell的困扰。
第三,docker logs只聚合了stdout和stderr,如果你的应用日志写到文件里,用docker logs是看不到的。需要把日志目录映射到宿主机或用日志驱动收集。这个属于进阶话题,但大部分新手都不知道,我提一嘴。
6. Docker Desktop路线的常见报错与性能陷阱
6.1 virtualization support not detected的三层排查链路
如果你选择Docker Desktop,大概率会遇到virtualization support not detected这个报错。我在前文提过三层原因:BIOS虚拟化功能、Windows虚拟机平台功能、第三方虚拟化软件冲突。这里我再补充一个排查顺序的建议,因为很多人一上来就去改BIOS,其实浪费了不少时间。
正确顺序应该是:先在任务管理器“性能”标签页看“虚拟化”是不是“已启用”。如果显示“已启用”,说明BIOS层面的虚拟化没问题,继续下一步;如果“已禁用”,再去BIOS里开。第二步用PowerShell检查:
Get-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform状态为Disabled就启用,别省这一步。最后才是考虑是否装了别的虚拟机软件。这个顺序可以帮你少走很多弯路。
还有一个经常一起出现的报错:wsl/service/createinstance/createvm/hcs/error_file_not_found。这个报错我之前遇到过两次,一次是Windows更新到一半被强制重启,还有一次是WSL的内核更新包损坏。解决方法很简单:以管理员身份执行wsl --update --web-download,再不行就把整个WSL重置一遍。这个报错字面上看起来像是“找不到文件”,很多人会去网上搜是不是系统文件丢了,其实根源就在WSL自身的组件一致性和版本不匹配上。
6.2 Docker Desktop的数据目录越用越大:VHDX膨胀问题
Docker Desktop在WSL 2后端模式下,所有的镜像和数据都存在一个动态增长的VHDX虚拟磁盘文件里。这个文件有个特点:只会变大,不会自动缩小。你删了一堆镜像、清理了构建缓存,磁盘文件也不会变小,Windows资源管理器里的C盘空间依旧被它占着。
解决这个问题的常规操作是手动压缩VHDX。首先在PowerShell里关闭所有WSL发行版:
wsl --shutdown然后用diskpart或者直接右键vhd文件“附加”,使用compact功能压缩。diskpart脚本大概是:
diskpart select vdisk file="C:\Users\用户名\AppData\Local\Docker\wsl\data\ext4.vhdx" attach vdisk readonly compact vdisk detach vdisk exit路径不一定是它,取决于Docker Desktop在你的机器上具体创建了哪些VHDX文件。你可以去这个目录下找一个叫ext4.vhdx的文件,大小通常有好几GB,那就是它了。
这个处理手法虽然有效,但更像是“亡羊补牢”。要从根源上避免,我建议平时注意清理无用镜像和构建缓存。docker system prune这个命令是个好东西,但用的时候要小心确认,因为它会删掉所有停止的容器、未被使用的网络、悬空镜像和构建缓存,误删后不可恢复。
6.3 /mnt/c的性能陷阱:跨文件系统IO为什么那么慢
无论你是用Docker Desktop还是直接在WSL里装Docker,只要你在WSL里挂载了Windows的盘符路径(比如/mnt/c),性能就会明显下降。原因在于WSL 2的跨文件系统访问是通过9P协议实现的,它介于Windows文件系统和Linux文件系统之间,每读一个文件都要经过协议转换和网络栈模拟,速度远不如在Linux原生文件系统上操作。
具体到Docker场景,最容易踩的坑是把宿主机目录挂载到容器里,而这个目录恰好位于/mnt/c下面。比如你在Windows的C:\work\nginx-html里放了几个HTML文件,然后用-v /mnt/c/work/nginx-html:/usr/share/nginx/html去挂载。这样确实能改挂载目录下的文件立即生效,但请求量稍微大一点,Nginx的IO就非常不给力,磁盘密集型任务会卡到怀疑人生。
正确的做法是把需要高性能IO的文件放在WSL自己的文件系统里,比如~/docker-html/下面,再挂载到容器,性能就正常了。Windows那边想编辑的话,可以在Windows资源管理器地址栏输入\\wsl$\Ubuntu-Docker\home\dev\docker-html,通过网络路径直接访问WSL文件系统。这样既保持了编辑的便利性,又避免了跨文件系统的性能损耗。
我实测过同一个Nginx容器,挂载/mnt/c下的静态页面和挂载Linux本机目录,在并发请求下的吞吐量差距可以达到好几倍。所以如果你对IO敏感,这个细节值得重视。
6.4 如何让Docker Desktop与WSL共存而不打架
很多人装了Docker Desktop之后,又想在WSL的Ubuntu里装一套Docker Engine,结果发现两边都有Docker命令,环境十分混乱。这个问题的根源在于,Docker Desktop安装在WSL里配置了一些PATH和上下文切换。
我的建议是尽量二选一。如果真的两个都装,那就要明确区分:在WSL的Ubuntu里,如果默认的docker命令指向了Docker Desktop的客户端,那你可以用docker context ls查看当前上下文,用docker context use desktop-linux或docker context use default切换。WSL发行版内安装的Engine对应的上下文是default,Docker Desktop对应的是desktop-linux。
但说实话,在同一台机器上维护两套Docker环境,偶尔还会出现一台机器上两个dockerd都在运行,端口冲突的诡异问题。所以我的最终建议是:想清楚了就选一边。日常开发测试,直接WSL内装Engine就够了;有图形化或K8s需求,就用Docker Desktop,但在WSL的Ubuntu里就别再装一套dockerd了,直接用Desktop的客户端连接过去。
7. 一点收尾的心里话
折腾了这么多年Windows下的Docker环境,我最终固定的方案是:WSL 2 + Ubuntu 24.04 + 原生Docker Engine,遇到需要可视化调试的时候,偶尔也会打开Docker Desktop看一眼。比起折腾安装本身,我更在意这个环境能不能稳定地跑起来,毕竟容器是为业务服务的,环境只是手段不是目的。
如果你现在刚开始走这条路,我建议顺着这篇文章的顺序:先把WSL 2安好,把虚拟化和内核这两个坎跨过去,再决定用哪条Docker路线,接着配好镜像加速,用MySQL和Redis这种经典镜像练手。整个过程下来,你对WSL、Docker、Linux发行版、容器网络的认知会立刻立体起来,以后再遇到任何Linux服务器上的部署问题,都可以在Windows上用这套环境直接模拟。最后再分享一个小技巧——把常用的docker run命令整理成Shell脚本,或者直接写一套docker-compose.yml,每次拉新环境时跑一遍就能恢复所有服务,省事又省心。