我在Windows上装Docker Desktop,第一次就被虚拟化检测卡住了。我是网络工程师,平时跟路由器、交换机打交道比较多,一开始面对“Docker Desktop failed to start because virtualisation support wasn't detected”这行报错,说实话是有点懵的。后来把BIOS、WSL2、Hyper-V、npipe这一串东西全部过了一遍,才算真正把Docker在Windows上跑了起来。如果你也是网络工程师,或者刚接触Docker,正准备在Windows上装Docker Desktop,这篇笔记应该能帮你少走很多弯路。
1. 这篇笔记解决什么问题:网络工程师为什么要碰Docker
先说结论:Docker这东西,对网络工程师来说不是“可学可不学”的加分项,而是能实打实省时间的工具。我自己的日常工作里,有大量场景需要临时搭一个服务来验证问题,以前要么找台服务器装环境,要么在自己电脑上折腾一套本地环境,过程繁琐、污染系统、还容易搞出奇怪的依赖冲突。用Docker之后,很多事情变成了“一条命令起环境,一条命令删掉”,干净利落。
-
快速搭测试环境:比如验证MySQL的某个参数、Redis的持久化策略、Nginx的反向代理行为,这些在网络排障和方案验证里经常用到。以前你要下载安装包、配置服务、处理依赖,半小时起步;现在一条 docker run 就能起一个完全隔离的环境,测完就删,不污染宿主机。
-
复现网络故障:容器里跑tcpdump、跑ping、跑telnet、跑curl,比在宿主机上抓包更干净。你想模拟“某个端口不通”“某个DNS解析失败”,很容易在容器里构造场景,不会把生产环境的配置搞乱。
-
验证网络策略和端口规划:作为网络工程师,你关心防火墙放通哪些端口、负载均衡怎么转发、应用的端口监听在哪个网卡上。容器可以把应用封装成一个个“小黑盒”,你只需要关心宿主机端口和容器端口的映射关系,这个思路跟NAT、端口映射很像,学起来会很有亲切感。
本系列第01篇聊的是Docker的基础概念,包括镜像、容器、仓库这些基本逻辑。这一篇是Series 02,重点非常明确——把Docker运行环境在Windows上抓到手里,让它能正常启动、拉得到镜像、跑得起容器,同时把启动过程中的常见坑都填一遍。适合Windows上首次接触Docker的运维、开发、网络工程师,以及所有被“Docker Desktop起不来”折磨过的人。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 装Docker Desktop之前,先把Windows环境收拾利索
很多人的安装失败,不是因为Docker安装包有问题,而是Windows环境本身没准备好。我踩了一圈之后发现,前置准备做扎实了,后面能少掉80%的报错。
2.1 Windows build号:决定你能不能装的硬门槛
Docker Desktop对Windows版本有硬性要求,不是你随便一台Windows 10都能装。Docker Desktop 4.x要求Windows 10 64位,且版本在21H2(build 19044)以上,或者Windows 11。低于这个门槛,安装器会直接提示“We've detected that you have an incompatible version of Windows”,然后拒绝正常工作。
查看自己系统版本,最快的方式是Win+R输入 winver,会弹出一个“Windows版本”窗口,里面有版本号和build号。我见过不少同事在这翻车——系统是Windows 10但build号偏旧,怎么装都报版本不兼容。应对思路就两条:能升级就Windows Update升级到最新;不能升级(比如公司电脑受限)就老实评估一下是否非要Docker Desktop,实在不行可以用WSL2里的Docker Engine做替代,但那套上手成本要高不少,不推荐新手折腾。
| Windows版本 | build号要求 | 是否支持Docker Desktop 4.x |
|---|---|---|
| Windows 10 21H2及以上 | 19044+ | 支持 |
| Windows 10 1909/2004/20H2 | 19041/18363等 | 通常不支持或体验不好 |
| Windows 11 | 全系 | 支持 |
2.2 BIOS虚拟化:报错里最常见的幕后黑手
Docker Desktop在Windows上跑Linux容器,本质上需要虚拟化能力来支撑。如果BIOS里没开虚拟化,后面一定会遇到那个经典报错:“Docker Desktop failed to start because virtualisation support wasn't detected”。
怎么快速检查你的CPU虚拟化是否已经开启?打开任务管理器,切到“性能”页,选中CPU,看右下角“虚拟化”一栏,是“已启用”还是“已禁用”。如果是“已禁用”,就需要进BIOS开启。
BIOS入口各品牌不一样,一般开机时按Del/F2/F10/F12,进Advanced或CPU Configuration,找“Intel Virtualization Technology”(Intel平台)或“SVM Mode”(AMD平台),设为Enabled,保存重启。这一步卡住的人很多,特别是一些办公电脑出厂会默认关闭虚拟化。如果你是在VMware或VirtualBox里装了一台Windows虚拟机来跑Docker,那还得在虚拟机设置里开启“嵌套虚拟化”,比如VMware的处理器设置里勾选“虚拟化Intel VT-x/EPT或AMD-V/RVI”,否则里面怎么开BIOS都没用。
注意:某些国内常见办公安全软件或者系统优化工具会修改启动项,干扰虚拟化设备的正常运行。如果确定BIOS已开启但任务管理器仍显示禁用,可以先用
bcdedit /set hypervisorlaunchtype auto(管理员命令行)检查一下Hyper-V引导配置,必要时恢复默认再重启。
2.3 WSL2和Hyper-V:Docker Desktop在Windows上的两种活法
Docker容器本质上是Linux进程,依赖Linux内核的cgroups、namespace这些特性。Windows上直接跑Linux容器,需要一层虚拟化支持。Docker Desktop给Windows用户提供了两种backend:WSL2 backend和Hyper-V backend。
现代Docker Desktop默认推荐用WSL2 backend,理由是更轻量、启动更快、内存占用更小。它的原理是:Windows通过WSL2跑一个真正的Linux内核,Docker引擎运行在这个Linux环境里,容器也就有了家。WSL2的安装和配置,是Docker Desktop能否正常工作的核心前提,很多“WSL update failed”“Docker Desktop-未安装WSL”的报错,根源都在这。
在管理员权限的PowerShell里执行以下命令:
powershell复制wsl --install
wsl --set-default-version 2
wsl --update
第一条命令会安装WSL功能,第二条把默认版本设为WSL2,第三条更新内核。装完建议重启一次系统。
检查WSL状态:
powershell复制wsl --status
wsl -l -v
wsl -l -v会列出你当前的发行版及版本号,如果版本列是1,需要手动转换:
powershell复制wsl --set-version <发行版名称> 2
还要提醒一下,WSL2默认会把虚拟磁盘文件放在C盘用户目录下,用久了容易把C盘占满。我习惯在用户目录下建一个.wslconfig文件,限制一下内存和CPU,顺便把swap位置挪走。.wslconfig内容参考:
ini复制[wsl2]
memory=4GB
processors=2
swap=2GB
localhostForwarding=true
这个文件放在 %UserProfile%\.wslconfig,重启WSL后生效(wsl --shutdown)。
3. Docker Desktop安装细节:默认路径和“D盘安装法”
前置环境收拾完,安装Docker Desktop本身就不容易出错,但有两个细节值得单独说:安装器的选项选择,以及如何让Docker的“数据大头”不占用C盘。
3.1 下载、安装、首次启动
去Docker官网下载Docker Desktop Installer.exe。安装过程中会有一个选项界面,里面有几个勾选项,重点是把“Use WSL 2 instead of Hyper-V”勾上。这个选项决定Docker Desktop使用WSL2作为后端,别选Hyper-V,选错的话后续体验会差很多。其他选项像“Add shortcut to desktop”可以随意。
装完之后它会提示需要注销或重启。重启后首次打开Docker Desktop,可能会再次要求安装WSL更新组件,按提示操作即可。如果你已经按第2章把WSL2和内核都更新过一遍,这一步通常能顺利通过。
第一次启动会花一点时间,托盘图标会转圈,等到图标稳定了,说明引擎起来了。打开PowerShell验证一下:
powershell复制docker version
输出里会分Client和Server两部分。只要Server端有响应,就说明引擎跑起来了。如果只有Client没有Server,那就是引擎没起来,后面第4章会讲怎么排查。
3.2 把Docker的数据盘挪到D盘
装到D盘这件事,很多人第一反应是“安装的时候选路径”。但Docker Desktop的官方安装器并不是很人性化,新版其实不支持直接修改程序安装路径,装完默认就在C盘。不过说实话,Docker Desktop程序本体占空间不算大,真正让你C盘告急的是WSL2的虚拟磁盘文件——Docker拉取的镜像、创建的容器数据,全都存在一个叫 ext4.vhdx 的虚拟磁盘里,这个文件会随着你使用越来越膨胀。
我的做法是把WSL2的发行版整体挪到D盘。有两种方式:
方式一(WSL新版本推荐):
powershell复制wsl --shutdown
wsl --manage docker-desktop --move D:\DockerData\docker-desktop
如果你的WSL版本够新,wsl --manage <发行版> --move <路径> 一步到位,直接把虚拟磁盘迁移。注意docker-desktop是Docker Desktop自己创建的后端发行版,在wsl -l -v里能看到。
方式二(通用导出导入法):
如果方式一的命令不支持,用传统的导出导入:
powershell复制wsl --shutdown
wsl --export docker-desktop D:\backup\docker-desktop.tar
wsl --unregister docker-desktop
wsl --import docker-desktop D:\DockerData\docker-desktop D:\backup\docker-desktop.tar
--unregister会把原来的发行版从WSL列表里删掉,慎重操作,所以先确认导出成功。导入之后Docker Desktop下次启动会在新位置找到虚拟磁盘。如果因为版本差异导致Docker Desktop找不到发行版,最稳妥的方案是直接清理所有docker相关WSL发行版,用Docker Desktop的Troubleshoot里的“Reset to factory defaults”重新初始化。
建议:迁移之前保存好你的镜像或Dockerfile,毕竟谁都不想折腾完发现数据丢了。日常使用中也要留意C盘剩余空间,Docker的镜像仓库和卷数据增长比你想象得快。
3.3 第一次跑通hello-world
环境全部就绪后,先跑一个最经典的hello-world镜像验证链路:
powershell复制docker run hello-world
这条命令做完三件事:检查本地有没有hello-world镜像,没有就去Docker Hub拉取,然后创建并运行容器。看到欢迎语输出,就说明你的Docker Desktop已经是“能干活”的状态了。如果这里卡住,大概率是镜像拉取慢或完全拉不下来,直接跳到第5章配置镜像加速。
4. Docker Desktop启动失败排查:那些报错我全踩过一遍
这一章是重头戏。搜索热词里关于Docker Desktop启动失败的提问特别多,我自己的安装过程也把大部分报错都遇了一遍,下面按报错出现的频率和排查逻辑来写。
4.1 virtualisation support wasn't detected:先从任务管理器查起
报错原文大概是:Docker Desktop failed to start because virtualisation support wasn't detected。这个报错意味着Docker Desktop在准备虚拟化环境时,检测不到虚拟化能力。我的排查链路是这样的:
第一步:打开任务管理器-性能-CPU,看虚拟化状态。如果是“已禁用”,直接进BIOS开启Intel VT-x或AMD SVM,重启。
第二步:如果任务管理器显示“已启用”,但Docker还是报这个错,检查Windows功能里“虚拟机平台”和“Hyper-V”有没有开启。控制面板-程序-启用或关闭Windows功能,把“虚拟机平台”勾上,“Hyper-V”也可以勾上(如果是Windows Pro/Enterprise版)。注意勾选之后需要重启。
第三步:如果还是不行,要怀疑是不是在虚拟机里跑的Windows。在网上搜“virtualization support not detected”的人很多其实是在VMware里开的Windows。这种情况需要在VMware虚拟机设置-处理器-勾选“虚拟化Intel VT-x/EPT或AMD-V/RVI”这一项嵌套虚拟化选项。VirtualBox类似,在系统-加速里打开“嵌套VT-x/AMD-V”。
这个报错的根因九成都是BIOS虚拟化没开或嵌套虚拟化没开,不是Docker本体损坏。
4.2 incompatible version of Windows:build号不够的应对
Docker Desktop启动时如果检测到Windows版本太旧,会弹“We've detected that you have an incompatible version of Windows”。我之前在一台Windows 10 1809的机器上装Docker Desktop 4.2x就遇到了它,弹窗提示版本不兼容。
解决办法:要么升级系统到Windows 10 21H2以上或Windows 11,要么用旧版Docker Desktop(不推荐,安全性和功能都跟不上)。如果你连升级系统的权限都没有(比如公司域控电脑),那可以试试在WSL2里直接装Docker Engine,不装Docker Desktop,风格更“命令行一点”,但能绕开Docker Desktop对Windows版本的检查。
4.3 WSL update failed:WSL就是起不来的处理
Docker Desktop启动时挂在这里的报错很多变体,常见的有“Docker Desktop - WSL update failed”和“Docker Desktop-未安装WSL”。这类问题本质是WSL环境没初始化好。
完整解决流程如下,所有命令都以管理员身份运行PowerShell:
powershell复制wsl --install --no-distribution
wsl --update
wsl --set-default-version 2
wsl --shutdown
然后打开Docker Desktop重试。如果还不行,检查 wsl -l -v,确保有发行版存在且版本是2。如果列表为空,先建一个发行版,比如:
powershell复制wsl --install -d Ubuntu-22.04
装完再回头启动Docker Desktop。
还有一个很隐蔽的问题:有些电脑曾经装过WSL1的发行版,Docker Desktop要求的是WSL2,但系统里存在WSL1发行版时会导致Docker Desktop启动异常。用 wsl --set-version 把相关发行版转成2,或者直接 wsl --unregister 删掉不用的发行版。
4.4 Failed to connect to the Docker API:当客户端找不到引擎
这个报错很经典:failed to connect to the docker api at npipe:////./pipe/dockerdesktoplinuxengine。npipe是Windows下的命名管道,Docker客户端通过它跟引擎通信。报这个错,翻译成人话就是“客户端找不到引擎进程”。
从网络工程师的角度看,这很像“ping不通某台服务器”——先得确认对端还活着。我的排查顺序是:
第一步:看Docker Desktop托盘图标,如果还在转圈说明引擎还没就绪,等一会儿再试。第二步:打开WSL命令行,跑 wsl -l -v,看看docker-desktop发行版是否处于Stopped状态。如果Stopped,执行 wsl --shutdown 后重启Docker Desktop。第三步:检查Windows服务里有没有 com.docker.service,确保它是运行状态(services.msc)。第四步:前几步都不行,大概率是Docker Desktop配置文件坏了。关闭Docker Desktop,到 %AppData%\Docker 目录下,把 settings-store.json 或必要时的整个配置目录备份后删掉,再启动Docker Desktop。
这里要提醒一下,别急着卸载重装。卸载重装只能解决软件本体损坏的问题,解决不了WSL层、配置层的问题。
4.5 卡在Starting:最后的核弹级手段
“Docker always starting”这个状态也很常见。图标一直转圈,日志里没有明确报错,就是起不来。可能的元凶有:WSL内核太旧、杀毒软件拦截、环境变量里代理配置异常、旧版Docker Toolbox残留冲突。
排查顺序:
- 执行
wsl --update更新内核,然后wsl --shutdown,重启Docker Desktop。 - 检查环境变量HTTP_PROXY/HTTPS_PROXY是否被设置成某个不可达的代理地址。国内办公环境尤其容易踩这个坑,因为某些内网工具会把代理写进系统环境变量,Docker Desktop启动时尝试连接代理失败,就一直卡在Starting。清除全局代理环境变量后重试。
- 暂时关闭杀毒软件或防火墙,看看是不是被拦截了。确认后记得给Docker Desktop加入白名单。
- 如果以上都不行,就上“核弹级”手段:打开Docker Desktop的Settings-Troubleshoot,执行“Reset to factory defaults”,或者干脆卸载干净(包括WSL发行版)重装。
大部分情况下,遇到Docker Desktop起不来的问题,先
wsl --shutdown再重启Docker Desktop能解决一半;先升级WSL内核再重启能再解决两成;剩下的才需要动配置和重置。
5. 镜像加速:给docker pull踩一脚油门
环境跑起来之后,第一个头疼的问题就是拉镜像慢。干净环境里执行 docker pull mysql:8.0,网速不好时能等到怀疑人生。这在国内网络环境里非常常见。
5.1 为什么在Windows上拉镜像总是慢半拍
Docker默认的镜像仓库是Docker Hub,它的服务器主要部署在海外。从国内直接访问,速度自然快不了。网络工程师就很好理解:你的主机到Docker Hub的跨国链路带宽、延迟、拥塞都不是你能控制的。所以在Docker Desktop里设置一个镜像加速器,相当于在中间加了一个“CDN”或者“缓存代理”,让docker pull从距离你更近、网络条件更好的地址拉取数据。
5.2 配置registry-mirrors的正确姿势
打开Docker Desktop,进入Settings-Docker Engine,你会看到一个JSON格式的配置文件,这就是守护进程的daemon.json。在JSON里增加 registry-mirrors 字段:
json复制{
"registry-mirrors": [
"https://你的专属加速器地址"
]
}
点击“Apply & restart”后,Docker Desktop会重启守护进程。
镜像加速器地址的选择有一个建议:优先用云厂商控制台提供的专属加速器地址。比如阿里云容器镜像服务控制台里有“镜像加速器”页面,登录后能看到一个专属地址,形如 https://xxxx.mirror.aliyuncs.com,匹配你的账号,配额和保障都比公共源稳定。有些高校和开源社区历史上提供过公共镜像源,但可用性变化很快,今天能用明天不一定能连,所以我不建议只依赖某个公共地址。如果你用的是自己搭建的代理镜像仓库,也是填在这个字段里。
5.3 验证加速有没有真的生效
配置完重启之后,先确认配置生效:
powershell复制docker info | Select-String -A 5 "Registry Mirrors"
在Linux或WSL里可以用:
bash复制docker info | grep -A 5 "Registry Mirrors"
能看到你配置的地址就说明Docker已经读取了新配置。然后随便拉一个镜像测试速度:
powershell复制docker pull mysql:8.0
如果速度有明显改善,配置成功。如果拉取还是慢,可以考虑换一个加速器地址,或者在拉取时指定更具体的tag(比如不要latest,直接指定8.0.x版本),也能避免一些不必要的流量消耗。
6. 网络工程师视角的第一个实战:跑起MySQL和Redis
环境通了,镜像能拉了,接下来直接上实战。我建议网络工程师的第一个Docker实战就做两个东西:一个MySQL 8.0,一个Redis主从。为什么选这两个?因为它们涉及端口映射、数据持久化、容器间通信这三个最核心的容器网络概念,搞懂这三个,以后用别的中间件都触类旁通。
6.1 部署MySQL 8.0:端口映射与数据持久化
执行以下命令:
bash复制docker run -d \
--name mysql8 \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=123456 \
-e MYSQL_ROOT_HOST=% \
-v mysql-data:/var/lib/mysql \
mysql:8.0
逐个参数拆开讲,这是新手最容易懵的部分:
-d:后台运行。--name mysql8:给容器起个名字,后面管理都靠它。-p 3306:3306:端口映射,宿主机3306映射到容器3306。左边是宿主机端口,右边是容器端口。这个逻辑跟网络工程师做DNAT映射几乎一模一样——所有访问宿主机3306的流量会被转进容器的3306端口。-e MYSQL_ROOT_PASSWORD=123456:设置环境变量,这里是初始化MySQL root密码。-e MYSQL_ROOT_HOST=%:允许root从任何主机连接,方便你用宿主机上的客户端工具连。生产环境不建议这样,但本地测试很省事。-v mysql-data:/var/lib/mysql:数据卷挂载。把容器里的/var/lib/mysql目录挂到Docker管理的一个命名卷里,容器删了数据还在。
命令敲下去之后,用 docker ps 看容器状态,如果STATUS列是Up,说明容器已经起来了。首次启动MySQL要做初始化,日志会刷一段时间。用 docker logs mysql8 能看到初始化进度。
然后用宿主机上的任何MySQL客户端连接测试:
bash复制mysql -h127.0.0.1 -P3306 -uroot -p123456
能连上就说明端口映射和数据持久化都没问题。
6.2 部署Redis主从:用自定义网络打通容器间通信
MySQL是单个容器,Redis主从则需要至少两个容器互相通信。如果你直接用默认的bridge网络,两个容器之间靠IP通信没问题,但每次重启IP都可能变,很不方便。Docker提供的自定义网络自带DNS解析,同一网络里的容器可以用容器名互相访问,这个功能在网络工程师眼里就是“内网DNS服务”。
先创建自定义网络:
bash复制docker network create redis-net
启动Redis主节点:
bash复制docker run -d \
--name redis-master \
--network redis-net \
-p 6379:6379 \
redis:7 \
redis-server --appendonly yes
注意多了 --network redis-net,把容器放进自定义网络。--appendonly yes 开启AOF持久化。
启动Redis从节点:
bash复制docker run -d \
--name redis-slave \
--network redis-net \
-p 6380:6379 \
redis:7 \
redis-server --replicaof redis-master 6379
关键点是 --replicaof redis-master 6379:从节点会把自己绑定到名为redis-master的节点上。因为两个容器在同一个自定义网络里,Redis会自动解析redis-master这个容器名,找到主节点的IP。这就是容器网络内DNS自动解析的威力。
验证主从状态:
bash复制docker exec -it redis-slave redis-cli info replication
输出里能看到role:slave、master_host:redis-master、master_link_status:up,说明同步关系已经建立。
6.3 用网络工程师的眼光看Docker网络模型
跑通上面两个实验之后,值得停下来想想Docker网络到底是怎么回事,因为这对网络工程师来说几乎就是“老朋友”。
默认情况下,Docker会创建一个名为bridge的虚拟网桥,对应Linux里的docker0,网段是172.17.0.0/16。每创建一个容器,Docker就会在里面创建一个虚拟网卡,分配一个172.17.0.x的地址,然后把这个虚拟网卡“插”到docker0上。你可以想象成一台二层交换机上反复插新设备,交换机自己有一个管理地址(172.17.0.1)。从容器向外访问网络,走的是docker0上的NAT,类似家里路由器上联出口的感觉。
查看当前网络的命令:
bash复制docker network ls
输出里通常有bridge、host、none三种网络。bridge是默认网桥,host容器直接共享宿主机网络栈,none是完全隔离。自定义网络也是基于bridge类型,只是额外增加了DNS解析能力,这在多容器场景下比默认bridge好用得多。
再回头看端口映射:-p 3306:3306 的实质,就是在宿主机网络栈上创建一个监听规则,把到达宿主机3306端口的流量转发到指定容器的3306端口。从网络工程师的角度理解,这跟端口映射NAT是一回事。
还有一个进阶工具强烈推荐:nicolaka/netshoot镜像,它是一个“网络工程师瑞士军刀”合集镜像,内置了tcpdump、ping、traceroute、mtr、dig、nmap等常用排查工具。可以这样用它进入另一个容器的网络命名空间:
bash复制docker run -it --rm --network container:mysql8 nicolaka/netshoot
进去后你能直接抓mysql8这个容器的网络包、测它的DNS解析,甚至做tcpdump抓包,排查容器内网络问题非常方便。这个工具我在实际排障中用了很多次,比一个个进容器装包高效太多。
7. 日常高频命令与维护技巧:从入门到能干活
Docker用起来是否顺手,取决于你对高频命令的熟练度。我把自己最常用的命令整理了一下,也在每个命令后面写了实际使用场景。
7.1 必会命令速查表
| 命令 | 作用 | 我的实际使用场景 |
|---|---|---|
docker ps |
列出运行中的容器 | 每天看容器状态,确认哪个服务挂了 |
docker ps -a |
列出所有容器(含已停止) | 排查之前启动失败但没删除的容器 |
docker images |
列出本地镜像 | 看本地都有哪些镜像,清理空间时用 |
docker pull 镜像名 |
拉取镜像 | 部署新服务前下载镜像 |
docker run -d --name xxx -p 端口:端口 镜像 |
创建并后台运行容器 | 部署MySQL、Redis、Nginx等 |
docker exec -it 容器名 bash |
进入容器内部 | 查日志、查配置、手工验证 |
docker logs -f 容器名 |
实时查看容器日志 | 排查应用启动失败原因,比看文件日志省事 |
docker stop 容器名 |
停止容器 | 维护或删除前停服务 |
docker rm 容器名 |
删除容器 | 清理不再用的容器 |
docker rmi 镜像名 |
删除镜像 | 清理本地镜像,释放磁盘 |
docker system df |
查看Docker磁盘占用 | 发现C盘空间不足时第一时间查看 |
docker system prune |
一键清理无用数据 | 定期清理悬空镜像和停止的容器 |
建议新同学把上面表格逐条过一遍,尤其是 docker system df 和 docker system prune,这俩是Docker用的时间长了之后一定会用到的“磁盘清理神器”。容器和镜像文件不会自动消失,不清理的话C盘分分钟被填满。
7.2 docker exec -it 的实际用法与踩坑
docker exec -it 是进入容器的标准姿势,但你可能会遇到两个坑。
坑一:容器里没有bash。 很多精简镜像(比如Alpine)只装了sh,没有bash。如果提示 bash: not found,换成:
bash复制docker exec -it 容器名 sh
坑二:进容器之后想退出但不想让容器停止。 在容器终端里直接输入 exit 会退出shell,如果它是这个容器的主进程,容器会退出停止运行。想优雅退出并保持容器后台运行,按 Ctrl+P 再按 Ctrl+Q。
如果在容器里需要复制文件出来或拷文件进去,可以用:
bash复制docker cp 容器名:/路径/文件 宿主机路径
docker cp 宿主机路径 容器名:/路径
排障的时候,我经常这样把容器里的日志或配置文件复制到宿主机上慢慢看,比在容器里用vim方便多了。
7.3 容器权限问题的定位思路
Windows上使用Docker Desktop,遇到“permission denied”的概率比Linux上小,但一旦遇到,通常是容器内部的权限问题。比如MySQL容器以mysql用户运行,你往它的数据目录挂载卷时如果宿主机目录权限不对,它启动就会报权限拒绝。这种情况下可以临时用 --privileged 参数运行容器来排查,但只建议测试环境用,生产环境还是要严格按最小权限来做。
如果你习惯在WSL2终端里敲docker命令,偶尔会遇到:
code复制Got permission denied while trying to connect to the Docker daemon socket
这说明当前用户不在docker用户组里。WSL环境下执行:
bash复制sudo usermod -aG docker $USER
然后重启终端,或者wsl --shutdown重开WSL,权限即可生效。Windows PowerShell里的docker命令一般不会遇到这个问题,因为它走的是Windows的命名管道权限,Docker Desktop安装时会处理好。
排障还有一个很实用的习惯:遇到任何容器异常,先看日志,再进容器。docker logs 输出的信息往往已经指明了问题方向,很多人一上来就 docker exec 进容器瞎转,效率很低。这跟网络排障先看syslog再上设备抓包是一个道理。
说起来,Docker Desktop这个软件在Windows上确实有些“娇气”,第一周我差点把电脑重装了。但跨过启动和镜像加速这两道坎之后,后面基本就是一马平川。我给还在折腾的人一个建议:遇到问题不要急着卸载重装,先看日志,再按WSL状态、镜像源、配置、虚拟化这个顺序排查;如果某个时刻它怎么都起不来,先 wsl --shutdown 再重启Docker Desktop,十次有八次能救回来。下一篇我准备写Dockerfile和镜像构建
