Docker彻底卸载与三种环境安装:Ubuntu/CentOS/离线部署完整指南

发布时间:2026/10/19 5:29:32
Docker彻底卸载与三种环境安装:Ubuntu/CentOS/离线部署完整指南 1. 写在前面卸载和安装其实是同一件事的两面玩容器绕不开Docker绕不开的就是反复折腾环境。Docker文件卸载与三种环境安装这个标题看起来是两个操作实际在运维和开发场景里它是连在一起的旧版本卸不干净新版本就装不安稳装的方式选错了后面排查问题能让你怀疑人生。我最初接触Docker时也以为“卸载”就是一条命令“安装”就是官网复制粘贴结果被残留文件、socket服务冲突、存储驱动不匹配这些坑连环绊倒。后来在几台机器上反复练了几轮把卸载和安装的整个链路梳理清楚之后才意识到这两件事必须放在一起理解卸载的关键是“彻底”一个目录一个服务地清安装的关键是“匹配”不同的Linux环境要选对应的安装方式而不是一招通吃。这篇文章我打算按我自己的实操顺序来写先拆解Docker卸载为什么容易留坑再给出完整的卸载步骤然后分别讲Ubuntu系、CentOS系、离线环境三种主流安装方式每一步都附上参数说明和踩坑提醒最后补充安装完成后的配置验证与常见问题排查。适合刚入门容器、需要在一台机器上反复切换环境的人也适合要在多套系统上部署Docker的运维新手。2. 卸载前必读Docker到底在系统里放了哪些东西很多人卸载装不干净是因为根本不了解Docker在系统里“驻”了哪些位置。它不像普通软件那样装在一个目录里完事——Docker是一个client-server架构安装时会散落在系统的各个角落。我习惯把它的文件分成六类方便排查时对号入座。第一类是软件包本体也就是通过apt或yum安装的docker-ce、docker-ce-cli、containerd.io这些包。这类包由包管理器管理卸载时用remove或purge处理即可。第二类是数据目录主要是/var/lib/docker这是Docker默认的工作目录镜像层、容器层、卷数据全在这里。这一块最容易被忽略也是卸载重装后“空间没释放”的罪魁祸首。第三类是配置目录/etc/docker下面通常有daemon.json里面配置了镜像加速、存储驱动、日志参数。旧配置残留会导致新版本启动异常最常见的报错就是Failed to start Docker Application Container Engine。第四类是systemd服务单元包括docker.service和docker.socket这兄弟俩一个管常驻进程一个管socket监听。第五类是网络规则Docker默认通过iptables的NAT表做端口映射卸载后规则链条如果不清理同一台机器再装时可能遇到端口映射异常。第六类是用户组与运行时状态比如docker用户组、/var/run/docker.sock套接字文件、日志文件等等。为什么不能用粗暴的rm -rf /var/lib/docker加apt remove docker来结束战斗因为包管理器只负责移除自己登记过的文件数据目录、配置目录、socket文件、网络规则这些“野生”文件它管不着。你以为是卸载其实是留了一地半成品。而且包管理器记录还存在系统里重装时可能出现版本冲突报错“已安装的docker-ce版本和请求的版本不一致”——这就是当初没卸干净的代价。卸载前要做备份这一点比什么都重要。如果容器里跑着数据库或者关键业务数据先做卷的备份命令是docker run --rm -v volume_name:/data -v $(pwd):/backup alpine tar czf /backup/volume-$(date %F).tar.gz -C /data .把卷打成tar包放到当前目录。如果没有重要数据那就可以放心往下走了。3. Docker完整卸载实操流程3.1 停止服务与移除软件包第一步永远是停止服务而不是直接删包。如果dockerd还在运行删包时会有大量进程占用对应文件提示“设备或资源忙”而且容器里的进程还活着可能产生数据写入到已经被标记删除的文件里。打开终端依次输入sudo systemctl stop docker sudo systemctl stop docker.socket sudo systemctl disable docker sudo systemctl disable docker.socket第3、4行的disable是防止服务器重启后Docker又自动拉起。我最初图省事只stop不disable结果装完新版之后旧版服务又偷偷起来两个daemon抢同一份socket文件直接导致新版本起不来。这个细节后来被我写进了自己的检查清单。服务停止后开始移除软件包。Ubuntu或Debian系用sudo apt purge docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin注意这里用purge而不是remove。remove只删二进制文件保留配置文件purge连配置文件一起删。既然要彻底卸载配置文件一并带走。CentOS或RHEL系用sudo yum remove docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-pluginyum的remove比apt的remove更彻底会连带一些配置一起处理但真正干的活也只限于软件包层面。卸载过程中如果系统提示某些包被依赖、无法删除检查是不是有“container”相关的其他软件包在依赖它确认后一并移除即可。包移除之后顺手清理无用的依赖sudo apt autoremove这个命令会把当初因为安装Docker而自动装上的、现在没有人再使用的依赖包清理掉。我见过很多教程不写这行导致卸载完成之后系统里还留着几十个无用包重装时又和旧依赖版本冲突。3.2 清理残留目录、配置文件与运行时文件包删完了并不代表清理结束。接下来要处理前面说的“野生”文件。我一步步执行过无数遍建议按下面顺序来sudo rm -rf /var/lib/docker sudo rm -rf /var/lib/containerd sudo rm -rf /etc/docker sudo rm -rf ~/.docker sudo rm -rf /var/run/docker.sock sudo rm -rf /etc/apparmor.d/docker第一行/var/lib/docker是数据主目录清理后所有镜像和容器数据都会消失这步之前没有备份的话就再也没机会反悔了。第二行/var/lib/containerd是containerd运行时自己的数据目录很多人漏掉它。第三行是配置目录旧的daemon.json如果不删重装后Docker会读取里面的旧参数。第四行~/.docker是用户级别的配置和凭据在某些系统里存在config.json记录登录仓库时的认证信息。第五行是docker.sock套接字文件如果它在但dockerd不在客户端连接时会报“Cannot connect to the Docker daemon”——重装后这类假性故障很难排查。第六行是AppArmor规则Ubuntu系特有删除后避免规则残留限制新版本的进程行为。在Ubuntu系上还有一个容易忽略的点AppArmor profile残留。执行sudo aa-status检查如果输出里还有docker相关的profile条目执行sudo apparmor_parser -R /etc/apparmor.d/docker移除它。我在一台旧系统上吃过这个亏重装Docker后容器一直无法启动报错信息里有个奇怪的“permission denied”查了半天才发现是老的AppArmor规则在作祟。3.3 清理网络规则与用户组Docker安装时会在iptables里创建名为DOCKER、DOCKER-ISOLATION-STAGE-1、DOCKER-ISOLATION-STAGE-2的链并在FORWARD和NAT表里插入引用规则。卸载后这些链不会自动消失。如果不清重装后一旦Docker创建的链名和残留链冲突会让你排查到崩溃。检查残留链sudo iptables -t nat -L -n | grep -i docker如果看到DOCKER相关条目手动清理。稳妥的做法是重刷规则链sudo iptables -t nat -F DOCKER sudo iptables -t nat -X DOCKER sudo iptables -t filter -F DOCKER sudo iptables -t filter -X DOCKER sudo iptables -t filter -F DOCKER-ISOLATION-STAGE-1 sudo iptables -t filter -X DOCKER-ISOLATION-STAGE-1 sudo iptables -t filter -F DOCKER-ISOLATION-STAGE-2 sudo iptables -t filter -X DOCKER-ISOLATION-STAGE-2这组命令一句话说明白先清空链里的规则再删除链本身。注意FORWARD链里其他业务规则不要动只动Docker前缀的链。如果系统里同时装了Cilium或Calico这类网络插件它们的规则和Docker规则是分开的别误删。用户组清理sudo groupdel docker如果提示用户组正被占用先检查该组的用户grep docker /etc/group把组内用户移走或者临时切换到其他组再执行groupdel。这步很多人跳过但其实docker组不删新装Docker后旧组里的用户会直接拥有访问权限安全上就有隐患。3.4 验证卸载是否彻底清理完毕后不要急着立刻安装先花两分钟验证一下。第一确认没有docker进程在跑ps aux | grep -i docker正常应该没有任何docker相关进程。第二检查软件包列表里没有残留dpkg -l | grep -i docker # Ubuntu系 rpm -qa | grep -i docker # CentOS系没有输出就是干净的。第三尝试执行docker version应该提示命令找不到。如果提示找到了但不认识该命令说明还有二进制文件残留在PATH路径下执行which docker找到它并删除。第四检查端口占用ss -tlnp | grep 2375 ss -tlnp | grep 23762375和2376是Docker API常用端口如果在监听且没有进程信息显示多半是残留进程或socket文件还在。到这一步卸载才算真正完成。提示如果你只是想“重装一个不同版本”离线备份里记得提前保存旧版本的daemon.json关键参数比如镜像加速地址、代理配置。全删干净后重装这些配置需要重新写不要到时候拍脑袋。4. 三种环境安装方式逐一拆解“三种环境”我按最常见的Linux场景来划分Ubuntu/Debian系apt源、CentOS/RHEL系yum/dnf源、离线或内网环境的二进制安装。这三种方式覆盖了绝大多数开发机、服务器和隔离网络的部署需求。一定要先讲清楚为什么需要区分Docker官方针对不同发行版分别维护了软件源和依赖规则apt方式会自动处理依赖、升级和签名校验yum方式针对RHEL系有专门的内核模块检查而二进制方式可以完全脱离网络和软件源适合生产内网、离线机器或特殊架构平台。三种方式的核心差异我用一个表格概括安装方式适用环境优点缺点aptUbuntu/Debian系个人开发机、云计算主机依赖自动解析、升级方便源配置失败时易报错yumCentOS/RHEL系服务器、传统企业环境与系统整合度高、脚本化友好需要额外启用epel或扩展源二进制静态安装离线环境、受控网络、特殊架构不依赖包管理器、完全离线可控手动管理服务单元和升级4.1 Ubuntu / Debian系用apt源安装Ubuntu系的安装流程核心就一句话配好Docker官方源然后安装。但配源这个环节你可能会遇到网络问题、GPG签名问题。先安装依赖工具sudo apt update sudo apt install ca-certificates curl gnupg lsb-releaseca-certificates和gnupg一个是CA证书一个是GPG校验工具curl用来下载密钥lsb-release用来获取发行版代号。这四项是配源的前置条件缺一不可。接下来添加Docker官方GPG密钥sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg sudo chmod ar /etc/apt/keyrings/docker.gpg第一行创建keyrings目录第三行设置密钥文件全局可读。为什么是ar因为apt以root身份读取但某些工具可能以其他用户运行权限不够就读不到GPG密钥导致后续apt update报“NO_PUBKEY”错误。接下来添加软件源。这里有一个容易踩的坑不要用写死的仓库地址一定要用$(. /etc/os-release echo $VERSION_CODENAME)动态获取发行版代号。因为Ubuntu不同版本代号不同写死了换机器就报404echo deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release echo $VERSION_CODENAME) stable | sudo tee /etc/apt/sources.list.d/docker.list /dev/null如果Download.docker.com在你网络环境下速度不理想可以把域名换成距离你较近的公共镜像站点地址格式保持一致即可。换源后执行sudo apt update看到Reading package lists... Done之后正式安装sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin这里我把docker-buildx-plugin和docker-compose-plugin也装上了。前者是现代镜像构建工具后者是Compose插件。有些教程只装前三个包后面发现docker compose命令找不到又回头补装。别省这一步一次装齐。安装完成后先不要急着使用直接跳到第5节做验证和配置。如果apt报错“Package docker-ce has no installation candidate”多半是源地址不对回查一下VERSION_CODENAME是否为合法值或者执行apt-cache policy docker-ce看候选版本列表。4.2 CentOS / RHEL系用yum源安装CentOS 7还是8先确认版本cat /etc/redhat-releaseCentOS 7和8的安装有个小差异CentOS 7默认用yumCentOS 8用dnfdnf兼容yum命令。无论哪个版本流程是安装依赖工具、添加官方仓库、安装软件包。先配置yum-utils和依赖sudo yum install -y yum-utilsyum-utils提供了yum-config-manager命令用于添加和管理repo配置。接着添加Docker官方仓库sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo这一步执行后系统会在/etc/yum.repos.d/下生成docker-ce.repo文件。用vim查看一下内容确认baseurl指向的版本号与本机系统版本一致如果不一致可以手动调整。同一时间还需要确认CentOS系统本身能访问epel源或基础源因为Docker包依赖的核心组件如container-selinux有时不在Docker官方源里。如果yum install时报“Requires: container-selinux”先执行sudo yum install -y epel-release sudo yum install -y container-selinux然后正式安装sudo yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin这台机器装完Docker后系统里会自动生成group docker和docker.service。CentOS系安装时docker.socket这个服务其实是共存的别忘记启用它sudo systemctl enable --now docker sudo systemctl enable --now containerd最后验证服务状态sudo systemctl status docker状态为active (running)才算成功。如果状态是failed用journalctl -u docker --no-pager | tail -50查日志。常见报错是overlay2存储驱动不被内核支持CentOS 7需要先升级内核或改用vfs驱动。overlay2的详细说明和解决方法我放在第6节。4.3 离线/内网环境静态二进制安装第三种情况是在没有外网的机器上安装Docker。这种环境下的安装思路是在一台能联网的同架构机器上下载Docker静态二进制包打包拷过去解压后自行注册服务。先去Docker官方静态二进制下载页获取对应平台和内核架构的tgz压缩包。文件比较大通常几百MB。核对架构x86_64和ARM64的包不同混用会直接导致段错误或exec format error。下载后用U盘或内网传输工具拷贝到目标机器解压到/usr/local目录tar -xf docker-版本号.tgz -C /usr/local/这一步会将docker、dockerd、containerd、containerd-shim-runc-v2等可执行文件解压到/usr/local/bin。但是Docker的静态包并不自带systemd服务单元也不自带containerd的配置文件这些都需要手动创建。先创建/etc/systemd/system/containerd.service内容参考标准配置核心是执行containerd并让它带config.toml启动。然后创建Docker的systemd单元。以/etc/systemd/system/docker.service为例核心内容如下[Unit] DescriptionDocker Application Container Engine Afternetwork-online.target containerd.service Wantsnetwork-online.target Requirescontainerd.service [Service] Typenotify ExecStart/usr/local/bin/dockerd ExecReload/bin/kill -s HUP $MAINPID LimitNOFILE1048576 LimitNPROCinfinity LimitCOREinfinity Restarton-failure RestartSec3 [Install] WantedBymulti-user.targetTypenotify是Docker官方配置的标准写法意思是dockerd启动完成后会主动通知systemd而不是让systemd单纯等待进程存活。这样systemd能准确知道服务是否真正准备好了。如果这里写错比如写成Typesimple会出现服务状态变成active但Socket监听还没就绪的情况。保存后重新加载服务并启动sudo systemctl daemon-reload sudo systemctl enable --now docker静态二进制方式最大的坑是遗漏containerd配置文件。如果系统里没有/etc/containerd/config.tomlcontainerd可能用默认配置启动和dockerd的对接参数不匹配导致容器创建后进程立即退出。解决方法是先在联网机器上执行containerd config default config.toml生成模板再一起拷贝过去放到/etc/containerd/config.toml。另一个坑是没有cgroups管理工具。静态包自带runc但不带cgroups相关的systemd集成在CentOS 7这种老系统上可能报“failed to create task for container: failed to create containerd task: cgroups: cgroup mountpoint not found”。解决办法是安装cgroup服务或重新挂载cgroup具体命令视发行版而定。5. 安装完成后的系统配置与快速验证5.1 给普通用户使用权限第一次安装完Docker执行docker ps大概率会报Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock这是因为docker.sock的所有者是root用户组是docker组普通用户不在docker组里就没权限访问。解决办法sudo usermod -aG docker $USER newgrp docker这两行加完当前用户就能直接用docker命令了。如果还不行注销重新登录或者重启机器因为用户组变更只在新会话中生效。这个坑几乎每台新机器都会遇到属于Docker安装后最经典的“第一次使用故障”。5.2 配置daemon.json镜像加速、存储驱动与日志安装完成后我建议第一时间创建/etc/docker/daemon.json把基础参数一次配好。完整的示例{ registry-mirrors: [https://镜像加速地址], storage-driver: overlay2, log-driver: json-file, log-opts: { max-size: 100m, max-file: 3 }, iptables: true, live-restore: true }各项参数说明registry-mirrors——镜像加速地址用于加速从公共仓库拉取镜像。具体地址需要根据你所在网络环境选择可用的公共镜像加速服务各大云计算厂商都提供镜像加速入口把地址填进去即可。storage-driver——存储驱动现代Linux内核推荐overlay2。Docker默认auto模式在部分老内核上会退化成vfsvfs性能和磁盘占用都很差。所以手动指定overlay2更稳健前提是内核支持检查方式是cat /proc/filesystems | grep overlay。log-driver和log-opts——日志驱动和滚动策略。生产环境必须配置日志上限否则容器的json.log文件可能把磁盘写满。iptables——默认开启用于容器网络端口映射。如果你用host网络模式或自定义网络插件可以关掉但绝大多数场景保持true。live-restore——daemon重启时容器不停止。这个参数在重启Docker服务时特别有用避免一次性把所有业务容器干翻。配置之后重启Dockersudo systemctl restart docker5.3 三分钟跑通验证流程配置完成后按以下顺序验证docker version docker info docker run hello-world第一条命令会显示Client和Server版本。如果Client有版本而Server显示“Cannot connect to the Docker daemon”说明服务没起来。第二条命令会显示存储驱动、镜像加速地址、内存、CPU等系统信息。第三条命令会拉取测试镜像并运行一个简单容器输出Hello from Docker!表示安装验证通过。如果docker run hello-world卡在下载阶段且之前配置了镜像加速但依然慢检查daemon.json是否被Docker正确加载docker info | grep -i mirror看输出里有没有你填的加速地址。没有的话需要先重启Docker再试。5.4 设置开机自启多数Linux安装Docker后服务默认没有启用自启。要确保重启后容器服务自动拉起执行sudo systemctl enable docker sudo systemctl enable containerd使用静态二进制方式安装时这一步尤其重要因为systemd单元文件是我们手动创建的默认不会开机自启。加完enable命令之后可以顺手测试sudo reboot重启后第一时间检查docker ps能不能正常输出——这一步能把所有“服务没起来”“自启配置失败”的问题一次暴露。6. 常见问题与排查攻略6.1 apt/yum源未配置成功、GPG报错表现执行apt update时报NO_PUBKEY或者安装时报Package docker-ce is not available。逐条排查检查/etc/apt/sources.list.d/docker.list文件是否存在且内容正确特别是signed-by路径是否与之前创建的GPG密钥路径一致。更换镜像站后GPG密钥必须从原站下载。如果你把deb源里的域名换了但密钥仍用download.docker.com的gpg文件更新到镜像站后校验不受影响但如果镜像站要求独立密钥也得对应更换。Ubuntu下如果提示Obsolete版本代号检查/etc/os-release里的VERSION_CODENAME是否为空空的话换成具体代号。GPG报错的标准解法是重新导入密钥curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker.gpg sudo chmod ar /usr/share/keyrings/docker.gpg然后把源配置里的signed-by路径同步改成/usr/share/keyrings/docker.gpg。CentOS系常见表现yum makecache fast时提示Failed to synchronize cache多半是docker-ce.repo文件里的baseurl带了错误版本。打开repo文件手动检查cat /etc/yum.repos.d/docker-ce.repo确认baseurl的路径是linux/centos/7/还是linux/centos/8/与本机大版本不一致就手动改。6.2 服务启动失败Failed to start Docker Application Container Engine表现systemctl start docker报Job for docker.service failed。第一步查看日志定位根因journalctl -u docker --no-pager | tail -80第一类问题是daemon.json配置错误。比如JSON格式不合法、storage-driver方向不支持。把daemon.json临时改名重启再逐个缩减配置项定位。这是最常见的启动失败原因我建议先做这步。第二类问题是磁盘空间不足。/var/lib/docker所在分区不够时dockerd会中止启动日志里出现No space left on device。检查磁盘df -h du -sh /var/lib/docker空间不够就清理旧目录或者把数据目录迁移到大分区。迁移步骤是修改daemon.json里的>systemctl status containerd journalctl -u containerd --no-pager | tail -406.3 内核与存储驱动异常表现容器启动失败日志提示failed to mount overlay或operation not permitted。老内核比如CentOS 7默认内核对overlay2支持不够常见处理是升级内核或者退而把存储驱动改为vfs。改vfs很简单在daemon.json里把storage-driver改成vfs再重启Docker。但vfs性能差、磁盘占用高只作为临时方案。生产环境优先升级内核改用新系统。另外如果日志里出现overlayfs: xino feature is not supported这种warning一般不影响使用不必处理。6.4 权限问题docker.sock permission denied表现docker ps报permission denied。前面已经给了标准解法加入docker组。但如果用户已经在docker组里还报错检查socket文件归属或SELinux策略ls -l /var/run/docker.sock正常显示srw-rw---- 1 root docker。如果归属不对手动改sudo chown root:docker /var/run/docker.sock sudo chmod 660 /var/run/docker.sockCentOS下还要检查SELinux是否拦截了进程访问getenforce如果返回Enforcing可以临时setenforce 0验证确认是SELinux引发的再配置正确的SELinux策略或者在etc/selinux/config里改为permissive生产环境慎用。6.5 端口映射不生效或者网络异常表现容器正常运行但docker run -p 8080:80后访问不了服务或者同一机器上其他服务突然不可访问。卸载残留的iptables链会导致新Docker的NAT规则异常。清理方法参考第3.3节。如果清理后依然有问题重启Docker让规则重新生成sudo systemctl restart docker有一种特殊情况如果宿主机装了firewalldDocker默认会向firewalld注册规则。此时需要确认firewalld和iptables不冲突。检查firewalld的运行时状态firewall-cmd --list-all我遇到过一次很典型的场景firewalld和Docker抢iptables规则导致Docker端口映射正常但外部访问不到。最后是把firewalld对Docker网桥的流量设置为信任问题才解决。6.6 常见错误速查表报错信息可能原因快速排查方向Cannot connect to the Docker daemondockerd没启动或socket文件损坏检查systemctl状态、删除残留socket重启服务No space left on device/var/lib/docker分区满了df -h检查磁盘、清理无用镜像和日志Permission denied ... docker.sock用户不在docker组usermod -aG docker 或检查socket权限Error response from daemon: pull access denied镜像名写错或仓库未登录核对镜像名执行docker loginunable to prepare context: path not found构建上下文路径错误检查docker build路径是否存在flag needs an argumentdocker命令参数书写错误检查参数是否漏了值或引号问题driver failed programming external connectivity端口被占用或iptables规则异常ss检查端口、清理残留规则排查有个总原则先看日志再看配置最后动网络和内核。日志在journalctl -u docker或/var/log/docker配置文件在/etc/docker/daemon.json。顺序别乱很多问题都是被“猜测式重启”搞得更乱的。写在最后的一点实际操作体会我记得很早在一台测试机上做过一次完整的“彻底卸载→换源重装”当时把卸载清单整理成一条脚本每次折腾就执行一遍。后来踩得坑多了才发现最关键的并不是命令本身而是“卸载时把系统当全新系统来要求”。残留文件、残留服务、残留网络规则、残留用户组这四个只要有一个没清干净重装后一定会在某个诡异时刻冒出来。安装这一侧我最推荐新手还是用apt或yum官方源二进制方式虽然离线可控但服务单元和配置文件的坑太多适合有系统d管理经验的人用。装完之后不要急着跑业务先把daemon.json、镜像加速、存储驱动和日志滚动配好——这几个配置后期很难无痛修改尤其是data-root迁移和storage-driver切换轻则重启容器重则要重建镜像缓存。最后分享一个小习惯每次卸载前我会把当前docker version、docker info的输出去重存成对比文件重装后再跑一次diff用实际输出确认环境干净。没有对比就没有伤害有了对比你才能一眼看出旧环境还留下了什么隐形状态。这套流程我反复用确实节省了不少半夜排查的时间。