用 Windows 做容器开发的人,大概率都见过这么个场景:双击 Docker Desktop 图标,托盘图标开始转圈,主界面右上角一直停在 Starting。转三五秒倒没什么,转十分钟还是这个鬼样子,心态就有点崩了。我今天就把这个卡住状态的前前后后讲清楚,从卡在哪个环节、怎么判断,到怎么一步步救回来,照着步骤来基本都能解决。适合在 Windows 上做容器开发、经常重装系统或升级后遇到同样问题的人收藏。
这个“卡在 Starting”的问题看着单一,背后的原因可不止一种。Docker Desktop 不是一个孤零零的软件,它在 Windows 上的启动要牵动虚拟化服务、WSL 子系统、引擎进程和网络组件,任何一环掉链子,界面上都会表现为同一个“Starting”。所以第一步不是急着搜命令,而是先搞清楚它到底卡在哪。
1. 为什么卡在 Starting:启动链路和状态机制
1.1 Docker Desktop 在 Windows 上到底是怎么“起来”的
现在的 Docker Desktop 在 Windows 上默认走的是 WSL 2 后端,也就是说 Docker 引擎并不是直接在 Windows 里裸跑的,而是跑在 WSL 2 的专属发行版里。这个架构下的启动链路大致是这样:
- 你双击 Docker Desktop 图标,首先起来的是 GUI 管理进程。
- GUI 进程去调用 Windows 侧的后台服务,常见的包括 Docker Desktop Service、WSL 服务、Hyper-V 主机计算服务等。
- Windows 服务把 WSL 2 虚拟机拉起来,Docker Desktop 会在里面挂载一个管理用的发行版,老版本里还能看到
docker-desktop和docker-desktop-data两个发行版。 - WSL 发行版起来之后,Docker 引擎
dockerd才在里面启动,引擎初始化网络、存储、containerd 等组件。 - 引擎完全就绪后,Docker Desktop 的 UI 才会把状态从 Starting 切到 Running。
生活和电脑可以类比:GUI 是餐厅前台,Windows 服务是水电,WSL 2 是后厨,dockerd是厨师长。前台的“Starting”就是餐厅门口挂出的“准备中”牌子,后厨没点火、厨师没到岗或者水管没通,这块牌子就一直挂下去。
1.2 卡住的本质:三个环节,一个都没跑通
排查卡住问题,不需要细到每一行代码,先把问题收敛到三个层面就行。
- Windows 服务层:相关服务没启动,或者启动到一半崩了。
- WSL 子系统层:WSL 发行版没起来,内核版本不兼容,或者虚拟化组件被占用。
- Docker 引擎层:发行版起来了,但
dockerd初始化失败,比如网络组件残留、磁盘数据损坏、配置非法。
界面上那个转圈,本质是 UI 在等引擎返回心跳。引擎没给回应,界面就永远显示 Starting。所以看到 Starting,正确反应不是猜,而是先把“引擎到底起没起来”这个问题回答掉。
1.3 判断方向:先分清 UI 假死还是引擎真没起来
这里分享一个我非常依赖的快速判断法。别盯着那个转圈看,打开终端敲一条命令:
docker version如果输出里 Server 那一栏有版本号,说明引擎已经跑起来了,只是 UI 没刷新,问题大概率出在 GUI 进程本身。这时候走一遍重启 Docker Desktop 的流程基本就能解决。
如果输出是Cannot connect to the Docker daemon,那才是真正的“引擎没起来”,需要往 WSL、服务和配置方向排查。还有一种情况,界面转圈,但 CPU 占用很高,说明引擎还在努力初始化;CPU 占用几乎为零,那多半是某个进程挂死了,需要强制清理后重启。这个区分听起来简单,实际操作中能帮你省掉大量无用功。
2. 动手前先诊断:查日志、看服务、验命令
2.1 三分钟走查:一张检查单
处理问题前,我习惯先花三分钟把下面的清单过一遍,定位到具体层再动手,效率高很多。下面这张检查表可以说是我自己排查这类问题的固定流程,也推荐你按顺序走。
| 检查项 | 命令/位置 | 正常状态 | 异常处理 |
|---|---|---|---|
| 后端模式 | Docker Desktop → Settings → General | Use WSL 2 based engine 已勾选 | 勾选并重启 |
| WSL 发行版状态 | wsl -l -v | docker-desktop或其他发行版能启动到 Running | wsl --shutdown后重开 |
| 引擎连通性 | docker version | Server 段有版本号 | 重点查服务与日志 |
| 相关 Windows 服务 | net start过滤 Docker/WSL 关键字 | LxssManager、com.docker.service 等在运行 | 管理员身份启动 |
| 虚拟化状态 | 任务管理器 → 性能 → CPU | 显示“虚拟化:已启用” | 检查 BIOS 与冲突软件 |
| 磁盘空间 | 设置 → 系统 → 存储 | C 盘至少保留几个 GB 空闲 | 清理磁盘后再试 |
另外一个很容易忽略的点:如果你的电脑装了第三方虚拟机软件,并且正在运行,虚拟机相关的模块会占用虚拟化能力,导致 WSL 2 起不来或者很慢。这不是说两个软件一定不能共存,新版虚拟机软件通常能做到,但在 Docker 卡 Starting 的时候,先把其他虚拟化软件关掉再试,能排除掉一大半冲突问题。
2.2 从日志里找直接线索
如果检查单走完还是定位不了,就轮到日志出场了。Docker Desktop 的日志不难找:点击托盘图标,在菜单里找到 Troubleshoot,里面有获取日志的入口。日志文件一般落在系统目录下的Docker\log里,里面几个文本文件分别记录 GUI、后端和服务的运行过程。
嫌图形界面点来点去麻烦的话,我常用下面这条 PowerShell 命令直接从事件日志里筛出 Docker 相关报错:
Get-WinEvent -LogName Application | Where-Object { $_.ProviderName -match "docker" } | Select-Object -First 20 TimeCreated, LevelDisplayName, Message看日志的时候不要从头看到尾,文件很大会浪费时间。直接搜几个关键词:error、fail、wsl、vhd、exit code。如果日志里反复出现 WSL 发行版被终止或者退出码异常,那方向基本就在 WSL 层;如果出现磁盘、虚拟硬盘、disk not found之类的字眼,多半是 Docker 的数据盘坏了,后面第四节会专门讲。
2.3 docker CLI 是否可用是风向标
再强调一下docker命令行在排查中的价值。Docker Desktop 卡住的时候,很多人的第一反应是看 UI,但 UI 只是客户端,Docker CLI 才是直接和引擎对话的工具。在终端执行:
docker ps docker context lsdocker context ls能确认当前上下文是不是desktop-linux。如果 CLI 能正常用,说明引擎健康,你需要的只是把界面这个“报喜不报忧”的表层刷新过来;如果 CLI 连不上,再往深层挖。
还有一个经验:执行命令前先确认你的终端是不是管理员权限。很多服务操作需要管理员权限,我遇到过不少次是权限不够导致服务没拉起来,Docker 一直转圈,情况其实很简单。
3. 分层处理:从重启到修复组件的完整路径
3.1 第一步:彻底重启 Docker Desktop 与相关 Windows 服务
绝大多数卡住问题,第一步就能解决,但前提是“彻底”。所谓彻底,不是点一下托盘退出就完事,而是要保证相关进程、虚拟机、服务都干净地停下来再重新拉起。
具体操作顺序:
- 从托盘图标退出 Docker Desktop。如果托盘没有反应,打开任务管理器,结束所有和 Docker Desktop 相关的进程,注意别只结束主窗口进程。
- 以管理员身份打开终端,执行:
wsl --shutdown这条命令会把所有 WSL 发行版连同那个迷你虚拟机一起停掉。这相当于把后厨的电闸彻底拉掉,重新合闸后很多残留状态都会被清干净。
- 重启 Docker 依赖的 Windows 服务:
net stop LxssManager net start LxssManager net stop com.docker.service net start com.docker.service这里LxssManager是 WSL 的核心服务,经常被忽略;com.docker.service是 Docker Desktop 的辅助服务。如果系统里还有vmcompute、hns这两个服务,也可以一并重启。hns是 Host Network Service,负责容器网络,它残留异常时引擎往往会在网络初始化阶段卡住。
- 全部操作完成后,重新启动 Docker Desktop。
这套“先杀进程、再关虚拟机、再翻服务”的顺序是有讲究的。直接重启服务而不先执行wsl --shutdown,WSL 虚拟机的状态可能是错乱的,服务重启只是治标不治本。反过来,只重置 WSL 但服务层还残留着假死状态,也是一样。
3.2 第二步:检查 .wslconfig 与代理配置
如果重启大法没效果,下一步要检查的是 WSL 的全局配置。配置文件在用户目录下的.wslconfig,也就是%USERPROFILE%\.wslconfig。这个文件不是默认存在的,如果你没手动建过,可以直接跳过这一段;如果你配置过,仔细看几个参数。
常见的坑一个是把memory设得过大。WSL 2 的内存设置一旦超过物理内存的一半,系统响应会明显变慢,Docker 引擎初始化时可能直接卡到超时。另一个坑是processors设置成核心数的十倍或者设成 0,这类配置在某些 WSL 版本里不会报错,但行为非常诡异。再就是swap设成 0,内存一紧张整个子系统都会进入僵尸状态。
一个相对稳妥的%USERPROFILE%\.wslconfig参考配置是:
[wsl2] memory=6GB processors=4 swap=2GB localhostForwarding=true注意这个配置要根据机器实际配置调整。比如物理内存 16GB 的机器给 6GB 是合理的,如果物理内存只有 8GB,那就不要超过 4GB。配置改完之后,必须执行一次wsl --shutdown,再启动 Docker,配置才会生效。
代理配置也是我踩过不少次的地方。dockerd在 WSL 发行版里启动时,会读取环境变量里的代理设置。如果你在 Windows 上设置了系统代理,或者用户环境变量里存在http_proxy、https_proxy,而代理服务本身并不可用,Docker 引擎在探测外部连接时就会长时间卡住。排查方法是在终端执行:
set http_proxy set https_proxy如果发现这些变量指向了一个当前没在监听的端口,或者干脆是过期的配置,就在 Windows 系统设置里关掉不必要的代理,并清理环境变量,然后重启 Docker Desktop。如果你确实是在公司代理环境下工作,代理本身没问题,那就保持配置,重点检查代理服务的稳定性即可。
3.3 第三步:升级修复 WSL2 内核和虚拟化组件
很多时候,Docker 卡 Starting 和 Windows 自动更新有直接的因果关系。系统升级后,WSL 内核版本跟不上,或者虚拟化组件被更新过程搞成了半启用状态,Docker 里面那个发行版就起不来了。
首先是更新 WSL 本身。以管理员身份打开终端执行:
wsl --update新版 WSL 已经作为一个独立组件分发,这条命令会自动拉取更新。执行完再跑一下wsl --version,确认版本号已经变化。
如果更新过程报错,或者系统里虚拟化功能本身处于损坏状态,可以用 DISM 重新启用两个关键功能:
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart执行完这两条,必须重启 Windows。这一步做完再启动 Docker Desktop,你会发现大部分和“WSL 内核太旧”相关的 Starting 问题都消失了。
顺带提醒一句,虚拟化功能是否正常,不只看 BIOS 里的开关。如果设备厂商的固件升级、其他虚拟机软件抢占资源,都可能导致 Hyper-V 层不可用。排查时在任务管理器的性能页看一眼虚拟化状态,如果显示“已禁用”,先去 BIOS 确认开关;如果显示“已启用”但 Docker 仍然卡,再考虑是不是第三方虚拟化组件占用。
3.4 第四步:清理 Docker 配置与重置引擎数据
走到这一步,启动链路里的常规嫌疑基本排完了。如果 Docker 还是赖在 Starting 不动,大概率是 Docker 自身的数据或配置出了问题。
最直接的手段是使用 Docker Desktop 自带的故障排查功能。在 Settings → Troubleshoot 里能找到重置入口,官方叫法是清理或重置数据。执行这个操作会把镜像、容器、卷全部清掉,相当于给 Docker 做一次“恢复出厂设置”。注意这不是我推荐一开始就用的手段,因为数据损失是实打实的。做之前务必把还有用的镜像和卷先导走。
还有一种情况比较隐蔽:Docker 的数据盘文件损坏。新版 Docker Desktop 会在本地目录里保存一个虚拟磁盘文件,名字类似docker_data.vhdx。如果系统异常断电或者蓝屏,这个文件可能处于损坏状态,Docker 启动时一挂载就卡住。
这种场景下,可以在关闭 Docker Desktop 后,用管理员权限打开磁盘管理工具,尝试把这个虚拟磁盘以只读方式挂载。能挂载成功说明文件结构还能救,可以直接做数据备份;如果挂载也卡住,干脆把这个.vhdx文件改名备份,让 Docker 重新生成一个空白数据盘。但改名等于数据全部清零,必须非常确认里面没有需要的东西。
相对安全的数据备份方式是先用docker save把镜像导出,具体命令是:
docker save -o images.tar 镜像名1 镜像名2卷的数据可以用一个临时容器打包出来:
docker run --rm -v 卷名:/data -v %CD%:/backup alpine tar czf /backup/volume.tar.gz -C /data .这样操作后重置也好、删数据盘也好,至少核心数据还攥在手里。
3.5 第五步:卸载重装与数据保留迁移
如果上面四步全部走完还是卡,那才轮到卸载重装。这一步的目标不是简单地把软件卸了装新的,而是把系统里的残留配置也一并清掉,否则装多少遍都一样。
先按上面提到的办法备份镜像和卷,然后从控制面板或者系统设置里卸载 Docker Desktop。卸载完成后,检查下面两个目录是否还存在:
- 用户目录下 Docker Desktop 的配置目录
- 本地目录下 Docker Desktop 的数据目录
这两个目录里如果只剩残留,并且你已经确认不需要里面的数据,可以直接删掉。注意别把整个 AppData 目录清空,只处理 Docker 相关的部分就好。残留文件清完之后再安装最新版,装完不要急着创建镜像,先确认 WSL 2 后端已经勾选,然后跑一条:
docker run hello-world能正常输出欢迎信息,再开始恢复之前的镜像和卷。
这里要给一个很重要的提醒:重装不是万能药。如果你的问题根源是 WSL 内核损坏或者 Windows 服务本身有问题,重装 Docker Desktop 之后依然会卡在同一个地方。所以重装之前先确保 WSL 本身是健康的。怎么判断?直接在终端执行wsl -d docker-desktop或者进入任意一个发行版,如果 WSL 自己能正常启动,Docker 的问题才有资格归因到 Docker 自己头上。
4. 高频原因与避坑速查表
4.1 常见问题速查对照表
把实战里见过的高频问题整理成一个速查表,排查时直接对照,能省不少时间。
| 现象/错误提示 | 最常见原因 | 推荐处理 |
|---|---|---|
一直 Starting,且docker version连不上 | WSL 发行版没起来或引擎崩溃 | wsl --shutdown,重启服务 |
| 提示需要启用虚拟化 | BIOS 未开启或第三方虚拟化占用 | 进 BIOS 开启,或关闭冲突软件 |
| 日志出现 WSL kernel update 相关字样 | WSL 内核过旧 | 管理员执行wsl --update |
| 日志出现 vhd/disk 相关错误 | 数据盘损坏或磁盘空间不足 | 隔离/重建 vhdx,清理磁盘 |
| 环境变量里有无效代理地址 | 代理配置异常 | 清理http_proxy、https_proxy |
| 一直转圈但 CPU 居高不下 | 初始化资源不足或配置不合理 | 检查.wslconfig内存配置 |
| 日志出现 access denied / operation not permitted | 安全软件拦截 | 添加放行规则或干净启动排查 |
4.2 日常使用中如何降低再次卡住的风险
预防比修复重要,尤其是这种和环境耦合很深的问题。我自己的使用习惯里,下面这几条几乎成了铁律。
第一,不要用任务管理器强杀 Docker Desktop。直接结束进程会让 WSL 子系统和后台服务残留一堆半死状态,下次启动就是另一个 Starting 事故现场。要退出就连托盘菜单的退出一起用,或者用命令干净收尾。
第二,别手欠乱改.wslconfig。网上很多所谓优化配置,比如把内存调成 0、把 swap 关掉、把处理器数量拉满,都会让 WSL 处在不稳定状态。你当前默认没这个文件,反而最安全。
第三,Windows 更新后主动更新 WSL。这是最常见的隐藏雷区。更新完系统后,别急着开 Docker,先跑一遍wsl --update,再重启 Docker Desktop。我有段时间把这条养成习惯后,几乎再没遇到转圈超过半分钟的情况。
第四,定期清理不再用的镜像和悬空数据。长期开发的人机器上会堆大量无用镜像,数据盘占用会越来越大,最终拖累 WSL 发行版的启动速度。可以用docker system prune清理,但要看清楚提示,别把正在用的容器和卷误删。
第五,如果你是会把电脑休眠而不关机的类型,注意 Docker Desktop 在休眠恢复后也容易表现异常。我一般会在休眠恢复后先看一眼 Docker 状态,一旦发现卡在 Starting,第一时间执行wsl --shutdown再重开,而不是傻等。
4.3 冷门但高发的几个隐藏坑
还有一些不那么容易想到的原因,我单独列出来,因为现实中遇到时几乎没有新手能一眼看出。
系统时间不准确是一个。Docker 引擎在启动过程中需要完成一些安全校验,如果系统时间和真实时间相差太多,TLS 握手会失败,启动过程会卡住。排查的时候就看一下任务栏右下角时间,如果时间总是不对,去设置里打开自动同步,问题往往立刻解决。
Windows 快速启动也是一个常见干扰项。快速启动本质上是一种混合关机,它会让内核状态保持在半休眠状态。这种情况下,Docker 依赖的服务可能没有完全重新初始化。处理办法是把快速启动关掉,或者每次都执行一次真正的重启。很多老项目团队里的开发机,长时间不关机只睡眠,Docker 的卡住频率明显更高。
另一个隐藏坑是人为修改过 Docker Daemon 的配置。在 Docker Desktop 的 Settings → Docker Engine 里可以直接编辑daemon.json内容。如果往里面写了非法的 JSON 格式,引擎启动时解析失败,同样表现为 Starting。但这个时候日志里不会出现明显的 Docker 字样,而是会提示解析错误。如果前面的检查都不奏效,点开 Docker Engine 配置页看一眼,确认里面的 JSON 格式是合法的,这一步成本极低但常常被忽略。
最后再分享一个小技巧。如果你比较着急,而又只是想确认问题是不是出在 Docker 本身,可以临时切到 Windows 容器模式试试。具体是从托盘菜单切到 Windows containers,如果切换后能正常起来,说明 Docker Desktop 这个程序本身没问题,问题就锁定在 WSL 和 Linux 发行版这一侧;如果 Windows 容器模式也一样卡,说明安装层面出了问题,重装比慢慢排查更省事。这个方法不适合长期使用,但用来缩小问题范围非常有效。
我在实际排查中最深的体会是:不要一开始就重置、重装。这个 Starting 状态绝大多数根本不是“恢复出厂设置”能解决的,而是环境组件之间的协作问题。把这套从浅到深的排查顺序走一遍,前面几步往往就能解决九成的问题。就算最终要重置,你也知道自己丢的数据是什么、怎么提前备份,而不是两眼一抹黑。