news 2026/10/9 10:52:08

Windows下用Docker Desktop与WSL2实现Ubuntu与Windows共用Docker引擎

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Windows下用Docker Desktop与WSL2实现Ubuntu与Windows共用Docker引擎

在Windows上跑Docker,和WSL里的Ubuntu连起来用

“我开发机是Windows,服务器是Ubuntu,代码在Windows上写得欢,一上服务器就崩”——这种场景太常见了。以前我身边的同事总是在虚拟机里装个Ubuntu,再在虚拟机里装Docker,麻烦不说,每次启动虚拟机都要等半天,内存还被吃喝掉大半。后来我彻底换成了Docker Desktop + WSL2这套方案:Docker引擎跑在WSL2提供的轻量Linux环境里,Windows系统本身和WSL里的Ubuntu发行版共用同一个Docker引擎,两边敲docker命令都能正常操作,不用双系统、不用完整虚拟机、不用每次启动都等Linux开机。

这篇文章就是完整的实操记录,把从环境检查、WSL2安装、Docker Desktop配置,到Windows和Ubuntu两个终端共用一个Docker引擎的每一步都拆开讲透,把它说成“三分钟装完”稍微有点夸张,但如果你把前置的WSL2已经装好,安装Docker Desktop本身确实就是三分钟内的事。适合刚开始接触Docker的开发同学,也适合被虚拟机折腾到崩溃、想换一套轻量方案的从业者。文末是我踩过的一些坑和排查思路,希望能帮你绕开。

1. 核心概念与方案选型:为什么是Docker Desktop加WSL2

1.1 三种在Windows上跑Docker的方案对比

Docker本质上是Linux生态里的技术,容器直接共享宿主机的内核,所以想在Windows上跑Linux容器,核心问题只有一个:怎么给Docker一个Linux内核环境。市面上主流的方案有三种:

方案实现方式启动速度内存占用Windows版本要求典型问题
传统虚拟机(VMware/VirtualBox)虚拟机里装完整Ubuntu,再装Docker慢,需等系统启动高,整个Guest系统占用内存无资源消耗大、维护复杂、路径隔离割裂
Docker Desktop + Hyper-V用Hyper-V虚拟机承载Linux内核较快中仅专业版/企业版开启Hyper-V后与VMware冲突,部分工具的嵌套虚拟化会有麻烦
Docker Desktop + WSL2WSL2提供轻量Linux内核,Docker引擎跑在其中快,秒级启动动态分配,内存可回收Win10 2004及以上对老版本系统不友好,WSL本身升级有时出问题

我推荐第三种方案的原因非常实际。第一是资源开销小,WSL2不是完整虚拟机,它是一个由微软维护的轻量Linux内核加用户态环境,内存按需使用,空闲了会释放回Windows,而不是像Hyper-V那样一开机就划走几个G。第二是路径互通,Windows的盘符在WSL2里直接挂载到/mnt/c,两边访问文件非常方便,这点对于在Windows上写代码、想在Linux环境里跑构建调试的场景来说几乎是刚需。第三是Docker Desktop官方对WSL2集成是一等公民支持,不再需要用户自己跑到Ubuntu里安装docker-ce那一整套东西,桌面程序自动把引擎在后台管理好。

1.2 Docker Desktop与WSL2的协作原理

理解这套方案是怎么连起来的,遇到问题才不会发懵。Docker的架构本身是客户端-服务器模式:docker命令是客户端,真正干活的是一个叫dockerd的守护进程(daemon)。守护进程依赖Linux内核特性,比如namespace、cgroups这些容器运行的基础设施,所以它必须在Linux环境里跑。

Docker Desktop的思路是:把dockerd跑在WSL2启动的Linux发行版里,而Windows上安装的Docker Desktop程序其实是一个管理外壳,负责拉起WSL2、管理引擎生命周期、提供图形界面配置。客户端方面,无论你是从Windows的PowerShell还是从WSL里的Ubuntu终端敲docker命令,最终都会通过Docker Desktop建立的通道连到同一个dockerd上。

用生活里的事来做类比:dockerd就像一家餐厅的后厨,Windows和WSL里的Ubuntu终端就是两个不同的前台点餐窗口,菜单一模一样,后厨也是同一个。无论你在哪个窗口点餐,最后吃到的是同一口锅炒出来的菜。理解了这个模型,后面排查问题时思路就清楚了——报错说“daemon没启动”,先去看后厨是不是没开火;说“找不到docker命令”,推测是点餐窗口没接上后厨的通话线。

2. 环境检查与前置准备:装Docker之前的几件正事

2.1 检查Windows版本与虚拟化状态

安装Docker Desktop走WSL2方案,对操作系统版本有硬性要求:Windows 10版本2004(Build 19041及以上),或者Windows 11。老版本Win10在安装WSL2时会非常不顺利,毕竟是依赖WSL2内核组件的功能。查看版本的办法是按下Win + R,输入winver,弹出的窗口里能看到系统版本和内部版本号。如果版本不够,别急着装Docker,先把Windows更新打全再说。

其次是虚拟化支持。WSL2本质上仍然需要CPU的硬件虚拟化能力(Intel VT-x或AMD-V)。打开任务管理器,切到“性能”标签,点击“CPU”,右下角有一项“虚拟化:已启用”就说明没问题。如果显示“已禁用”,需要重启电脑进BIOS(开机按Del/F2/F10等,不同主板不同),在CPU设置里找到Intel Virtualization Technology或SVM Mode之类的选项,设为Enabled保存重启。这一步不做,后面装WSL2会直接报错。

注意:有些本子是低端型号或者BIOS锁得死,虚拟化选项被隐藏了。这种情况在家庭版Windows上尤其麻烦,但一般主流的近五年Intel和AMD平台都没问题,不用太担心。

2.2 安装WSL2和Ubuntu发行版

安装WSL2现在比前几年简单太多了。以前需要手动下载安装包、开启Windows功能、重启、再装发行版,一套流程要折腾半小时。现在只要用管理员权限打开PowerShell或者Windows Terminal,执行下面这一条命令:

wsl --install -d Ubuntu-22.04

这条命令会自动开启VirtualMachinePlatform和Microsoft-Windows-Subsystem-Linux两个Windows功能、安装WSL2内核、下载Ubuntu 22.04发行版,然后提示你重启。重启完成后,Ubuntu会自动完成初始化流程,设置一个用户名和密码,之后就能进入Linux终端了。

装完以后,建议立刻用这条命令确认WSL的版本是2,而不是默认的1:

wsl -l -v

如果显示某发行版的VERSION列是1,手动升级到2:

wsl --set-version Ubuntu-22.04 2

为什么一定要VERSION是2?因为WSL1是翻译层方案,不提供真正的Linux内核,Docker Desktop依赖的很多内核特性在WSL1上根本跑不起来。WSL2才是一个轻量虚拟机,有完整内核,Docker引擎能直接跑。这一点是整套方案的地基,地基错了,上面全是白搭。

另外提一个很多人在意的问题:WSL的默认安装位置是C盘,Ubuntu的根文件系统会以ext4.vhdx虚拟磁盘文件存放在C:\Users\你的用户名\AppData\Local\Packages下的发行版目录里。如果你C盘紧张,建议在安装前就改路径,或者装完后用wsl --export和wsl --import迁走。后面我在问题章节里讲迁移细节,这里先记住有这回事。

3. Docker Desktop安装与关键配置:三分钟装完,但配置要用心

3.1 下载安装与模式选择

Docker Desktop的安装包直接从官网docker.com的Products页面下载,选Windows版即可。下载下来是Docker Desktop Installer.exe,双击开始安装。安装过程中有一个组件选择界面,默认会勾选“Use WSL 2 instead of Hyper-V”,这个选项务必保持勾选。如果机器上已经装了WSL2,安装程序会直接识别到,不需要额外操作。

安装结束会让你退出并重新登录,或者干脆重启电脑。重启完成后第一次打开Docker Desktop,会弹一个协议确认框,点接受就行。如果之前没装WSL2,Docker Desktop安装时可能也会自动帮你拉起来,但顺序上我建议还是先手动装好WSL2,因为这样发行版、版本号、路径这些东西可控制。后面遇到“Docker Desktop安装了但起不来”的问题,大概率就是WSL2没装全。

启动后看Docker Desktop主界面右下角的鲸鱼图标,如果显示“Engine running”状态是绿色,说明引擎已经在跑了。这时候打开Windows的PowerShell,执行docker version,能看到Client和Server两部分信息都正常返回,其中Server部分说明引擎地址和内核版本。如果只看到Client信息、Server部分报错,多半是引擎没起来,往下看问题排查章节。

3.2 设置里那些必须搞懂的配置项

Docker Desktop装完不是直接用就完了,几个关键设置直接影响使用体验和稳定性,我第一次用的时候就是没仔细看设置,吃了不少亏。

资源限制(Settings -> Resources):默认情况下WSL2可能会占用大量内存,尤其你同时开着多个容器时,内存容易被吃光。这里可以手动限制WSL2使用的CPU核数和内存大小。我的建议是内存限制到物理内存的一半左右,给Windows本身留足余量。这个值不是越大越好,WSL2里容器跑太多本来就会拖慢整体机器,限制住反而更稳。

WSL集成(Settings -> Resources -> WSL Integration):这是“让Ubuntu和Docker连接起来”的核心开关。打开设置面板,在WSL Integration部分能看到你安装的发行版列表,比如Ubuntu-22.04,把对应的开关打开,Apply & Restart。这一步做完,Ubuntu终端里才能直接敲docker命令。有很多人装了Docker Desktop,但Ubuntu里跑docker却提示command not found,原因就是集成开关没开,或者是开了但没重启。

镜像加速(Settings -> Docker Engine):这个属于老生常谈的问题了,拉取镜像慢几乎是国内用户的共同痛处。在Docker Engine的配置文件JSON里加上registry-mirrors配置,可以大幅提升拉取速度。配置完点击“Apply & Restart”,引擎会用新的配置重启,之后docker pull的速度体验会好很多。

{ "registry-mirrors": [ "https://docker.m.daocloud.io", "https://dockerproxy.com" ] }

这块不能说得太细,网上教程也多,用的时候注意甄别加速地址的可用性,失效了换一个就行。

镜像存储位置(Settings -> Resources -> Advanced):Docker Desktop默认把镜像数据存放在WSL的vhdx虚拟磁盘里,也就是C盘。镜像拉多了会很快占满空间。在Advanced里可以修改“Disk image location”到其他盘,或者在设置里直接看到当前磁盘占用情况。定期用主界面左侧的“Clean / Purge data”功能清理悬空镜像和构建缓存,也能释放不少空间。

4. Windows与Ubuntu(WSL)的Docker连接实操:从验证到部署一个MySQL

4.1 打通两边终端的Docker命令

先把集成开关打开并重启Docker Desktop,然后分别打开Windows PowerShell和Ubuntu终端,在两个终端里都跑一下docker version。正常的话,两边都会显示一样的Server信息,说明它们连的是同一个dockerd。如果Ubuntu里提示docker: command not found,先检查集成开关,再检查Docker Desktop是否处于运行状态。注意,WSL里的Ubuntu终端其实是一个独立的bash环境,它本身不装Docker客户端,docker命令是由Docker Desktop在启用集成时注入到WSL环境里的。所以千万不要在Ubuntu里自己去apt install docker.io,那样会装出第二个Docker引擎,反而把整条链路搞乱。

打通之后用一个小命令验证整套链路是通的:

docker run --rm hello-world

如果一切正常,会打印一段话说明你的Docker安装和运行是成功的。容器跑完就退出,因为加了这个参数容器不会常驻,这也是验证引擎最简单的办法。如果这一步就卡住,后面部署什么都会受影响。

4.2 两边共用引擎的上下文切换问题

有个概念值得理解一下:Docker的命令默认会走当前环境的“context”,上下文里定义了要连接哪个引擎。执行下面这条命令可以看到当前上下文情况:

docker context ls

在Docker Desktop + WSL2的默认情况下,输出会显示desktop-linux这个上下文,用的是Docker Desktop启动的引擎。Windows终端和Ubuntu终端访问到的都是它。只要你没有手动创建其他上下文(比如连了一个远程服务器上的Docker引擎),默认的desktop-linux就已经实现了两边共用。有些人在Ubuntu里配置了DOCKER_HOST环境变量指向某个远程地址,这时敲docker命令就会连到远程去了,和标题里的“建立连接”就不是一回事了,注意区分。

实际实操中,我更习惯直接在Windows终端里管理镜像和容器,在Ubuntu终端里跑一些需要Linux环境的东西,比如docker compose这种依赖Linux环境的命令,只要引擎共用,两边跑效果完全一致。

4.3 部署一个真实的MySQL容器做验证

验证一个方案能不能真正用在日常开发中,最好的办法是部署一个实际会用到的东西。这里用MySQL 8.0演示,命令如下:

docker run -d \ --name mysql8 \ -e MYSQL_ROOT_PASSWORD=123456 \ -p 3306:3306 \ mysql:8.0

逐行解释一下这条命令在做什么。-d表示后台运行,--name给容器起个名字方便管理,-e设置环境变量,这里给MySQL设置了root密码。-p 3306:3306是端口映射,意思是把WSL2内部容器的3306端口暴露到Windows的localhost:3306上,左边是Windows端口,右边是容器端口。最后mysql:8.0是镜像名加标签。

命令执行后,第一次会先拉取镜像,几百兆的镜像拉取时间取决于网络环境。启动后执行下面命令确认状态:

docker ps

输出里会看到mysql8容器的状态是Up,端口列是0.0.0.0:3306->3306/tcp。这时候在Windows的PowerShell里用Test-NetConnection或者直接用Navicat连接localhost:3306试试,能通就是成功。

这里有一个知识点大家经常忽略:-p 3306:3306实际是把端口映射到了Windows的localhost上,因为Docker Desktop做了端口转发,它会自动把WSL2虚拟机内部的端口转发到Windows宿主机。所以无论是Windows本地连接localhost:3306,还是在Ubuntu终端里连接localhost:3306,看到的都是同一个MySQL服务。这种透明访问是Docker Desktop方案体验最有优势的地方,不用手动配置复杂的网络。

4.4 路径挂载:Windows文件如何进容器

开发场景里经常需要把代码目录挂载进容器。Docker的-v参数可以绑定宿主机的目录到容器内部,比如:

docker run -d --name nginx-test -p 8080:80 -v /mnt/c/my_site:/usr/share/nginx/html nginx

这个挂载路径的写法是Docker Desktop + WSL2方案里最容易踩坑的地方。在Ubuntu终端里执行时,Windows的C:\my_site要写成/mnt/c/my_site,这是WSL2约定的挂载格式。在Windows PowerShell里执行docker run时,路径也可以直接用Windows格式,比如C:\my_site,Docker Desktop会自动转换。但是!如果你在Windows终端里用/mnt/c/my_site这种格式,或者在Ubuntu里用C:\my_site这种Windows格式,极大概率会挂载失败或者挂载到一个不存在的目录里。我的经验是:在哪个终端执行,就用哪个终端的路径习惯,不要混着写。

另外挂载要注意权限问题。Windows的文件系统(NTFS)挂载到WSL2里,用户权限映射有时候会出问题,容器的进程如果以非root用户运行,访问挂载目录可能报Permission denied。简单的处理办法是给容器加上--user root参数,但这只是权宜之计。更好的做法是在WSL2里设置/etc/wsl.conf文件里的automount选项,启用metadata,让挂载的目录支持Linux权限位,从根本上解决权限映射问题。

5. 常见问题与排查技巧实录

5.1 Docker Desktop启动后引擎一直不运行

这是最常见的问题。安装完了,双击Docker Desktop,界面一直显示“Docker Desktop starting”,转圈半天后报错或者状态变红。排查思路分三步走:

第一步,确认WSL2本身的发行版能正常启动。在Windows终端执行:

wsl -l -v

如果状态显示Stopped,手动wsl --shutdown再重新打开Ubuntu终端。如果发行版本身都不能启动,问题在WSL层面,不在Docker层面,先把WSL修好。

第二步,如果是升级完Docker Desktop或者Windows更新后出现的问题,通常执行一次wsl --shutdown,然后把Docker Desktop完全退出再重新打开,能解决大部分启动问题。因为Docker Desktop启动时需要重新初始化WSL里的引擎环境,shutdown之后所有状态会被清空重来。

第三步,如果重开还是不行,去Windows的事件查看器(eventvwr.msc-> Windows日志 -> Application)筛选来源为Docker的条目,看有没有具体的报错信息。这个报错信息才是真正能定位问题的线索,模糊排查会浪费大量时间。

5.2 报错:error during connect: This error may also indicate that the docker daemon is not running

这个报错在Windows和WSL终端里都可能出现,字面意思就是docker客户端连不上dockerd引擎。拆解一下原因:

第一种情况是最常见的:Docker Desktop压根没启动,或者启动但引擎还没ready。确认方法是看Docker Desktop主界面左下角状态,等它变绿再操作。

第二种情况是:你已经启动了Docker Desktop,但客户端连接失败。这时候执行:

docker context show

确认当前上下文是desktop-linux。如果是其他的,用docker context use desktop-linux切回来。

第三种情况会出现在Windows终端:报错提示里可能会带一小段话,类似error during connect: ... start the windows daemon from a non-elevated terminal。这种提示通常是因为Docker Desktop在非管理员权限下运行的终端里出现了权限问题,或者是Docker Desktop服务被限制在高权限模式下,而当前终端是非管理员权限,客户端访问命名管道时被拒绝了。最简单的处理办法:关闭Docker Desktop,用普通方式重新打开(不要用“以管理员身份运行”),同时在PowerShell里也直接以普通用户身份执行docker命令,不要开管理员权限的终端。Docker Desktop日常使用根本不需要管理员权限,开高了反而会造成权限不匹配。

5.3 Windows更新后WSL2失效

Windows大版本更新偶尔会把WSL2的内核组件冲掉,导致wsl -l -v时发行版状态变红或者报错“WSL仍在初始化”。处理方法是:管理员打开PowerShell,执行wsl --update,手动更新WSL内核。如果还不行,执行wsl --shutdown后重开。实在不行的,wsl --unregister 发行版名后重新安装发行版,注意unregister会删除该发行版的全部数据,操作前一定备份。

5.4 端口冲突:本地MySQL和容器MySQL

另一个高频踩坑场景是本地已经装了MySQL,默认占用3306端口,这时候想再起一个容器MySQL就会失败,报错通常类似Bind for 0.0.0.0:3306 failed: port is already allocated。解决办法很简单,映射端口改成其他值,比如-p 3307:3306,连接时用3307。这条命令背后其实也说明了端口映射的灵活性,左侧端口随意指定,右侧端口必须是容器内部程序的真实监听端口。别把两侧顺序记反了,右侧改错了服务根本起不来。

5.5 磁盘占满:WSL vhdx文件的迁移与压缩

用了一段时间Docker,磁盘空间越来越小,这是WSL2方案一个绕不开的话题。因为WSL的虚拟磁盘文件(ext4.vhdx)会随着镜像、容器和缓存数据的增加不断膨胀,而且删除数据后文件往往不会自动缩容,白白占着硬盘。

迁移方法是:管理员PowerShell执行wsl --shutdown退出所有WSL,然后导出到指定位置再重新导入:

wsl --export Ubuntu-22.04 D:\wsl\ubuntu-backup.tar wsl --unregister Ubuntu-22.04 wsl --import Ubuntu-22.04 D:\wsl\ubuntu D:\wsl\ubuntu-backup.tar --version 2

--import会重新把发行版注册到WSL里,但注意重新导入后默认用户会变成root,需要额外配置默认用户,或者进系统后用wsl --manage Ubuntu-22.04 --set-default-user之类的命令调整。这一套操作下来,新生成的ext4.vhdx是紧凑的,而且存放位置也搬到了D盘,C盘空间能释放不少。同理,Docker Desktop在设置里的“Disk image location”也能改镜像数据存储位置,建议在一开始安装完就把位置调整好,省得后期迁移麻烦。

6. 一些实操心得和后续扩展思路

用这套方案快两年了,整体体验就是四个字:省心、好用。相比以前开虚拟机,WSL2的启动速度基本是秒级,内存动态分配,不用操心在Windows和Linux之间复制粘贴文本(直接互通),也不用再装各种剪贴板共享增强包。配合Docker Desktop,Windows和Ubuntu共用引擎,开发环境的一致性得到了保证——我在Windows上写完代码,切到Ubuntu终端里跑同一套容器命令,结果完全一样,这在以前是不可想象的。

最后分享一个小经验:如果你同时用多个发行版,比如Ubuntu和Debian都有,Docker Desktop的WSL集成列表里可以同时开启多个,但建议日常只用一个发行版跑Docker引擎相关的操作,避免同时开启多个发行版导致资源消耗翻倍。另外,升级WSL内核时注意,Docker Desktop有时候依赖特定版本的内核,wsl --update之后如果Docker启动异常,直接重启电脑通常就能恢复。

这套环境后续能扩展的方向很多:比如用docker compose一套命令起前后端多个服务、在WSL2里配置GPU支持后跑深度学习容器、结合VSCode的Dev Containers插件做到真正的“代码在容器里开发”。每一个方向都值得单独写一篇,但基础就是今天这套Docker Desktop加WSL2的链路。把这条链路理解透了,后面怎么折腾都不怕。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/9 10:52:04

用YunYouJun cook自托管菜谱库,cpolar内网穿透实现远程访问

在手机备忘录里翻了三分钟,还是没有找到我妈要的那份红烧排骨做法之后,我决定动手把散落各地的菜谱彻底收编。最终落地的是两个工具的组合:YunYouJun cook 负责把私房菜谱变成清晰好用的网页应用,cpolar 负责给这台本机服务开一道…

作者头像 李华
网站建设 2026/10/9 10:52:01

MVVM与数据代理:Vue响应式原理及手写迷你实现

很多前端初学者接触Vue时,最先听到的两个词就是“MVVM”和“数据代理”。网上的教程大多一笔带过,要么说“Vue是MVVM框架”,要么说“data里的数据会被代理到vm上”,但很少有人把这两件事拆开讲透:MVVM到底解决了什么问…

作者头像 李华
网站建设 2026/10/9 10:50:49

前端锚点技术全解析:从平滑滚动到固定导航偏移的实战指南

1. 锚点技术到底是个什么东西第一次听到“锚点”这个词,很多人脑子里浮现的是船锚——把船固定在某个位置不让它漂走。网页里的锚点其实是一个道理:它把用户的视线“钉”在页面的某个具体位置上,不管这个位置在文档的哪个角落,点一…

作者头像 李华
网站建设 2026/10/9 10:50:43

Java AIO 百万级 MQTT 长连接实践:从线程模型到压测避坑

简介:基于 Java AIO 开发的低延迟、高性能百万级 MQTT 客户端组件与 Broker 服务,完整支持 MQTT v3.1、v3.1.1 和 v5.0 三套协议,也支持 WebSocket MQTT 子协议(兼容 mqtt.js)、HTTP Rest API、遗嘱消息、保留消息、自…

作者头像 李华
网站建设 2026/10/9 10:48:46

基于Kubernetes的CTFd动态靶场插件:从容器编排到实例回收

简介:针对CTF竞赛中动态题目靶场需要快速隔离、弹性伸缩与自动部署的需求,这份基于Kubernetes容器编排的CTFd插件实现源码与设计报告,适合信息安全、网络工程及计算机相关专业学生用于毕业设计或课程设计。资源共34个文件,含13个P…

作者头像 李华
网站建设 2026/10/9 10:47:29

深入拆解IEEE 754浮点存储:符号位、指数位与尾数精度边界

简介:面向C语言初学者与嵌入式笔试面试准备者的浮点型数据存储专题讲解,重点剖析单精度float与双精度double的字节占用、IEEE-754格式、符号位、尾数与指数偏移,并结合union共用体实例演示浮点数的内存布局,以及同一段数据从整型、…

作者头像 李华