首页 / 资讯中心 / 文章详情

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

Windows下用Docker Desktop与WSL2实现Ubuntu与Windows共用Docker引擎 ★ FEATURED ARTICLE
在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加WSL21.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版本2004Build 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而不是默认的1wsl -l -v如果显示某发行版的VERSION列是1手动升级到2wsl --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会弹一个协议确认框点接受就行。如果之前没装WSL2Docker 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 - AdvancedDocker Desktop默认把镜像数据存放在WSL的vhdx虚拟磁盘里也就是C盘。镜像拉多了会很快占满空间。在Advanced里可以修改“Disk image location”到其他盘或者在设置里直接看到当前磁盘占用情况。定期用主界面左侧的“Clean / Purge data”功能清理悬空镜像和构建缓存也能释放不少空间。4. Windows与UbuntuWSL的Docker连接实操从验证到部署一个MySQL4.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_PASSWORD123456 \ -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_siteDocker 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 DesktopWindows和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的链路。把这条链路理解透了后面怎么折腾都不怕。
阅读完成 · 觉得有帮助?
咨询建站