ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Docker安装避坑指南:从WSL2到Compose插件全流程解析

Docker安装避坑指南:从WSL2到Compose插件全流程解析 1. 为什么“装Docker”这种简单事偏偏天天有人翻车Docker这个东西凡是搞过部署、搞过开发环境的人应该都不陌生。很多人第一次接触它的原因特别朴素在本地装上MySQL、Redis、Nacos、GitLab再也不用忍受手动安装那一堆依赖和配置。但有意思的是越是这种“先装个环境再说”的工具越容易在第一道门槛上卡住。我经常看见有人在群里发报错截图最高频的几类就是Docker Desktop提示Virtualization support not detected、WSL2启动失败、装了Docker却找不到docker compose命令、镜像拉到一半就断流。这些问题的根源几乎都不是Docker本身而是宿主环境没有准备好。所以要写这篇安装方案我的思路不是丢给你两条命令就完事而是把Windows和Linux两条路线分别拆开讲清楚每一步为什么要这么做。顺带把装完之后的验证、镜像加速、权限配置、网络排查这些“后续动作”一并补齐。无论你是第一次装Docker的新手还是已经在生产环境里折腾过的老手这篇内容都能对应上你踩过或者将要踩的坑。先说一个最重要的认知Docker不是虚拟机。虚拟机是把整台机器虚拟化里面跑一个完整的操作系统资源开销非常大。Docker是共享宿主机内核只隔离进程、文件系统、网络这些用户态的东西所以启动一个容器几乎是毫秒级。但这个特性也带来一个硬性约束——它强依赖宿主机的内核特性比如Linux的cgroups、namespacesWindows上则依赖WSL2或者Hyper-V提供的虚拟化层。所以你会发现Docker安装失败往往不是Docker本身出了问题而是宿主机的CPU虚拟化没开、内核版本太老、WSL2没装好这类“环境病”。在动手之前你不妨先按下面这张表给自己定个位避免走弯路你的系统推荐方案安装之前必须确认的条件Windows 10/11Docker Desktop WSL2后端BIOS开启虚拟化系统版本不低于Win10 2004WSL2可用Ubuntu / Debian官方apt仓库内核版本不低于3.10能用systemd管理服务CentOS / RHEL官方yum仓库内核建议3.10以上老版本需考虑升级已经跑在云服务器上的Linux官方仓库方式确认发行版类型和CPU架构避免装了不匹配的包这张表其实就是我自己的选型逻辑。很多人一上来就问“Windows怎么装Docker”其实Windows上最顺滑的路就是Docker Desktop配WSL2不要去折腾老掉牙的Docker ToolboxLinux上我也不推荐直接用一键脚本虽然快但出了问题不好排查具体后面细说。2. Windows安装路线Docker Desktop与WSL2的那些纠缠Windows系统装Docker现在的标准答案就是Docker Desktop。但Docker Desktop本身只是个图形化管理器和CLI客户端真正干活的引擎其实是跑在WSL2里的Linux虚拟机里。这个设计很多人不理解为什么Docker Desktop非要绑定WSL2答案很简单Docker的容器技术天生是给Linux设计的Windows原生并不支持直接跑Linux容器。WSL2提供了一个轻量级的真实Linux内核Docker Desktop把引擎跑在里面性能接近原生文件IO也远好于一代WSL你在Windows里敲docker ps实际返回的是WSL2里那个Linux引擎的实时状态。整个安装过程我建议按下面的顺序走每一步都有它的目的。2.1 先把WSL2铺好别急着装Docker Desktop很多人的安装顺序是反的先把Docker Desktop下载下来安装完一启动弹窗提示要启用WSL2或者虚拟化然后才开始折腾底层。这个顺序浪费了不少时间。正确的顺序是先在Windows侧把WSL2准备到位。以Windows 11为例管理员身份打开PowerShell执行wsl --install这条命令会自动安装WSL本身、VirtualMachinePlatform功能组件并且默认安装一个Ubuntu发行版。装完后系统会提示重启。重启之后再验证一下WSL是不是真的跑在2代上wsl -l -v输出结果会显示每个发行版的名称、状态和WSL版本我记得如果WSL版本列显示的是1说明还停留在老模式需要手动升级wsl --set-version Ubuntu 2如果你不想在这个环节装任何Linux发行版也没关系Docker Desktop在检测到WSL2存在但没发行版时会自己创建一个专用的docker-desktop发行版来跑引擎。但个人建议还是装一个Ubuntu因为后面你大概率会用到WSL里的Linux环境去处理容器内的问题比如查日志、调试网络有个自己熟悉的发行版会顺手很多。这里有个特别常见的报错就是热搜词里那条Virtualization support not detected。我在帮别人排查时发现这个提示出现的原因大概有三层第一层是BIOS里没开CPU虚拟化Intel的VT-x或者AMD的SVM第二层是Windows的虚拟机平台功能没启用第三层是WSL2的核心组件没安装完整。排查路径也比较直接按下CtrlShiftEsc打开任务管理器切到“性能”标签看CPU那一栏有没有“虚拟化: 已启用”字样。如果显示未启用重启进BIOS找到Intel Virtualization Technology或者AMD SVM Mode设置为Enabled。在“启用或关闭Windows功能”里勾选“适用于Linux的Windows子系统”和“虚拟机平台”重启后执行wsl --set-default-version 2。如果以上都做了还是不行执行wsl --update更新WSL内核再跑一遍wsl -l -v确认状态正常。2.2 安装Docker Desktop并切换到WSL2后端WSL2就绪之后去Docker官网下载Docker Desktop安装包一路默认选项就行。唯一需要注意的是安装过程中弹出的“Use WSL 2 instead of Hyper-V”选项目前默认就是勾选的保持默认即可。安装完成打开Docker Desktop在设置里找到Resources - WSL Integration这里会列出你机器上已有的WSL发行版把Ubuntu那项打开。这一步的意义在于开启集成之后你在WSL的Ubuntu终端里直接敲docker命令能直接连接到Docker Desktop管理的引擎不需要在Windows和WSL之间来回切换上下文。启动之后如果一切正常托盘区的鲸鱼图标会变成绿色或者静止状态打开终端执行docker version能看到Client和Server两个区块的版本信息说明引擎已经跑起来了。如果Server部分是空的说明Docker Desktop还没完全起来等图标稳定了再试。2.3 npipe连接失败的排查链路有个搜索热词是failed to connect to the docker api at npipe:////./pipe/dockerDesktopLinuxEngine这是Windows下最容易遇到的启动故障之一。它的意思很直白Docker客户端尝试通过命名管道连接Docker引擎但引擎没回应。我遇到这个报错的经历挺有代表性。有一次是Windows系统更新之后Docker Desktop服务和WSL2内核的版本对不上了具体情况就是引擎起不来但托盘图标看着还在转。排查方案是这样的重启Docker Desktop不行重启WSL2还不行最后是执行wsl --shutdown确认WSL里所有发行版都停止后再重新启动Docker Desktop才恢复。核心原因就是WSL2的某个实例残留了僵死状态命名管道接口没有正常暴露出来。如果上面这套重置操作做了还是报错那就往更深一层排查检查WSL发行版是否损坏。在PowerShell里执行wsl --unregister docker-desktop这类命令时要非常小心这是删除Docker Desktop自己创建的WSL发行版删了之后Docker Desktop会在下次启动时重新创建不会影响你的用户数据但如果你对这套机制还不熟建议先把Docker Desktop完整关闭再操作或者直接走“设置-疑难解答-Clear Docker Desktop data”的官方清理路径。3. Linux安装路线Ubuntu和CentOS的仓库玩法Linux上装Docker说实话比Windows顺多了因为Docker本身就是从Linux生态长出来的。但也因为“太顺了”很多人反而容易被网上那些一键脚本带偏。3.1 为什么我坚持用官方apt仓库而不是curl脚本Docker官方文档上给过一个快速安装方式一句话命令curl -fsSL https://get.docker.com | bash这条命令确实省事但我后来在几台服务器上用过之后就不再推荐了。原因有三个第一脚本会从外网拉取二进制然后直接落到系统里你很难判断它到底改了哪些文件、写了哪些配置出了问题想卸载只能手动清理非常麻烦第二脚本方式装的Docker不会自动注册到apt或者yum的软件源里这意味着后续升级Docker版本时你还是得重新执行脚本无法用apt upgrade一键搞定第三在一些内网环境或者源被限速的场景下脚本拉包的稳定性远不如配置好官方源之后走包管理器的增量下载。所以我的标准做法是添加官方软件源然后用系统包管理器安装。这样装的Docker完全受包管理器管理安装、升级、卸载都干干净净排查依赖问题也容易。3.2 Ubuntu全流程安装命令以Ubuntu 22.04/24.04为例整个过程分为“加源”和“装包”两个阶段。先把依赖和证书工具装上sudo apt update sudo apt install -y ca-certificates curl gnupg然后下载并安装Docker官方的GPG密钥用来验证软件包签名sudo install -m 0755 -d /etc/apt/keyrings sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc sudo chmod ar /etc/apt/keyrings/docker.asc接着把Docker仓库写入apt源列表。这里有个细节很多教程在写仓库地址时用的是$(lsb_release -cs)这个命令来获取系统代号但如果你用的是某些基于Ubuntu的非官方发行版或者系统的/etc/os-release里写的是自定义代号就可能导致仓库地址解析错误。稳妥的做法是直接指定代号比如22.04对应jammy24.04对应nobleecho deb [arch$(dpkg --print-architecture) signed-by/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu jammy stable | sudo tee /etc/apt/sources.list.d/docker.list /dev/null更新索引并安装Docker引擎、CLI、容器运行时、Buildx插件以及Compose插件一次装齐sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin装完先不要急着用检查一下服务状态sudo systemctl status docker如果输出显示active (running)说明引擎已经起来了。再把开机自启打开sudo systemctl enable docker这里特别强调一点一定要在安装命令里带上docker-compose-plugin。Docker从20.10版本开始把旧版的docker-compose独立二进制重构成CLI插件命名也从docker-compose变成docker compose。如果你只装了docker-ce不带插件执行docker compose version时会直接报错提示找不到命令这个坑我在后文第4节还会专门展开。3.3 CentOS和RHEL系列的安装差异CentOS 7虽然比较老了但在很多存量服务器上依然是主流。Docker官方对CentOS 7的支持方式是提供x86_64架构的rpm包源。安装步骤和Ubuntu类似先把repo文件放到/etc/yum.repos.d/下sudo yum install -y yum-utils sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo然后安装sudo yum install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin启动并设置开机自启sudo systemctl start docker sudo systemctl enable dockerCentOS 7的用户还有一个值得注意的问题系统自带的yum源里Docker版本往往非常老比如docker-io或者更早的docker-engine这些老版本没有compose插件也缺乏后面生态需要的特性。如果你之前用yum装过旧版Docker建议先彻底卸载再装官方仓库版本否则两套Docker的二进制和配置文件会打架。卸载命令要同时清掉旧包和数据目录sudo yum remove -y docker docker-common docker-selinux docker-engine如果你在CentOS 7上装完新版Docker之后发现docker compose依然不可用先检查内核版本。CentOS 7默认的内核是3.10跑新版Docker虽然能勉强工作但容器网络、存储驱动这些方面容易出现兼容问题。热搜词里有一个是“centos7升级docker”我理解很多人其实是被旧版本的客户端坑了升级到官方源的新版docker-ce就能解决问题。3.4 装完Linux版Docker之后的权限处理刚在Linux服务器上装完Docker第一个遇到的坑几乎都是这个执行docker ps报权限错误提示连接不上Docker守护进程的socket或者干脆显示permission denied。这背后的原理是Docker的守护进程默认只监听在/var/run/docker.sock这个Unix socket上而这个socket所属的组是docker。普通用户不在这个组里自然没有权限和守护进程通信。解决办法不是用sudo去执行每条docker命令而是把当前用户加入docker组sudo usermod -aG docker $USER执行完这条命令之后必须重新登录终端或者重启会话让用户组变更生效。这里有个很多人没注意到的细节如果你在SSH会话里操作直接执行newgrp docker切换当前会话的组也很方便不需要断开SSH重连。然后验证一下docker run --rm hello-world如果你看到Hello from Docker!的输出说明权限和引擎都正常了。其实从架构角度来说这个权限设计是合理的——能访问docker.socket就意味着能操作宿主机上的全部容器相当于宿主机root权限因为你可以把宿主机的任意目录挂载进容器再逃逸出来。所以加入docker组本质上等于授予了高权限在多人共用的开发机上要谨慎管理docker组成员。安全要求高的话更推荐的方式是配置Docker的TLS证书让客户端通过HTTPS方式访问远程Docker API而不是共享本地socket。4. Docker Compose v2它不是旧版那个“docker-compose”Compose这个东西熟悉Docker的人都知道它解决的是“多个容器如何一键编排”的问题。以前定义一堆容器跑起来得写好几行docker run还要操心容器间的网络、挂载、依赖顺序有了Compose文件之后一个docker compose up -d就全搞定了。但这里有个非常隐蔽的命令坑无数人在新环境下敲docker-compose up -d结果提示命令找不到然后怀疑自己没装好。其实不是没装好是Compose的形态变了。4.1 独立二进制和CLI插件的区别老一代的Compose是一个独立的Python二进制包命令叫docker-compose安装方式可以是pip install docker-compose也可以是下载一个独立可执行文件放到/usr/local/bin下。那时候你得额外装Python依赖版本还经常跟Docker引擎对不上搞起来有点痛苦。从Docker 20.10开始Compose被重构为Docker CLI的插件命令变成了docker compose注意中间没有横杠。它的安装方式也变了——不再独立运行而是作为docker-compose-plugin这个包安装到Docker的插件目录里。Docker CLI在启动时会自动从插件目录加载docker-compose插件所以当用户敲docker compose时CLI发现这不是子命令就去插件目录里找可执行文件找到了就调用它。这个变化的好处很明显Compose和Docker CLI共用同一个版本管理和升级通道你不用再单独维护一套Python环境或者手动下载二进制了版本兼容性也好很多。坏处就是如果你还在用旧的安装习惯比如只装了docker引擎没装docker-compose-plugin那敲docker compose就会得到一句冷冰冰的提示docker: unknown command: docker compose而这个报错正好也是热搜词里出现频率很高的一条。它的本质就是Docker CLI没找到对应的Compose插件或者Docker版本太老20.10之前压根不支持插件机制。4.2 怎么判断Compose插件装没装对装完Docker之后一定要跑一下这个验证命令docker compose version正常输出会包含类似Docker Compose version v2.32.4这样的版本信息。如果提示command not found或者unknown command那就要按我前面说的检查是不是漏装了docker-compose-plugin。还有一种情况是你确实装了但装成了独立二进制的旧版Compose那么docker compose version依然可能不识别。新旧两种格式的命令可以同时存在但建议新环境只保留新的# 卸载旧版独立二进制式Compose sudo rm -f /usr/local/bin/docker-compose清理之后再验证一次。4.3 老的compose文件还能不能用很多人从旧版本迁移过来之前的项目时会有个疑问以前写的docker-compose.yml现在还能不能直接用答案基本可以因为Compose文件的schema主体没有大变最核心的services、volumes、networks这些定义都能沿用。但有几个细节值得注意。第一新版的Compose v2默认不再支持version: 3这种顶层字段你写上去的话它会给出一个警告建议删除。这本身不影响运行因为新Compose是自适应的不靠version字段决定解析行为。第二depends_on的语义在新版里更聪明了。旧版只是控制服务启动顺序新版在docker compose up时如果启用了--wait会真正等待依赖服务的健康检查通过再启动下游服务这是编排健壮性的明显提升。第三如果你以前的compose文件里写了docker-compose up加上-d的组合新版本里完全等价。但有一些参数名称微调了比如--no-recreate在新版本中可能需要用--no-recreate完整拼写缩写行为不如旧版宽容遇到参数不识别时先查版本差异。4.4 在安装方案里为什么要把Compose一次装到位我的观点是现在这个时间节点Docker和Compose已经强绑定了。不管你是“只部署一个小项目”还是“搭一套微服务测试环境”Compose都是绕不开的。因为docker run命令虽然灵活但每次创建容器都要手动指定端口映射、环境变量、挂载目录命令一长就非常容易出错。把配置沉淀成compose.yml文件至少有三个实打实的好处一是可版本管理二是不依赖记忆三是环境可迁移克隆一份compose文件就能在另一台机器上复现整套环境。所以在这篇安装方案里我把docker-compose-plugin直接放进了一开始的安装命令里这是典型的“一次到位”思路避免装完引擎再补刀。如果你已经按照前面Ubuntu那套命令走了现在可以确认一下docker compose version有输出了再看下面这个更实用的测试——随便建一个目录写一个最简单的compose文件services: whoami: image: traefik/whoami:latest ports: - 8080:80然后执行docker compose up -d docker compose ps curl localhost:8080能看到服务信息就说明Compose插件工作正常这套组合拳已经能支撑你继续折腾后面任何复杂的编排文件了。5. 装完先别急着拉镜像验证、加速与配置安装完成的标志不是肉眼看到“Docker Desktop图标变绿”或者“docker命令能敲了”而是引擎真正能跑容器、镜像能正常拉取下来。这一步看着简单但里面埋了不少配置层面的问题最常见的两个就是镜像下载慢和日志文件无限增长。5.1 hello-world只是最低标准我见过很多人在服务器上跑完docker run hello-world之后就觉得自己Docker装好了然后开始拉MySQL、Redis结果发现镜像源慢得离谱一顿饭吃完还没拉完一个镜像。docker run --rm hello-world这个镜像极小它实际上只是验证引擎能创建容器、拉取镜像、执行二进制并不代表你的网络和镜像源配置是好的。真正的安装验收我建议是拉一个稍大一点的常用镜像比如Nginx或者Redisdocker pull nginx:alpine这个镜像体积小又能覆盖镜像源、分层拉取、网络连通性这些关键链路。拉完之后顺手跑起来docker run -d -p 8080:80 --name test-nginx nginx:alpine curl localhost:8080能返回Nginx欢迎页那才算安装验证真正通关。5.2 镜像下载慢资深的做法是配registry mirror镜像源问题是国内用户绕不开的切肤之痛。Docker Hub在国外直接从官方源拉取时间极长优化方案就是配置镜像加速器也就是registry mirror。原理不复杂docker daemon在拉取镜像时如果配置了mirror会优先从mirror地址拉取这个mirror通常是Docker Hub的只读缓存能显著减少跨洲网络损耗。配置方式在Linux和Windows上略有不同。Linux上直接编辑/etc/docker/daemon.json{ registry-mirrors: [ https://docker.m.daocloud.io, https://dockerproxy.com, https://docker.nju.edu.cn ] }然后重启Docker服务sudo systemctl daemon-reload sudo systemctl restart dockerWindows的Docker Desktop则简单一些在Settings - Docker Engine里直接编辑右下角的JSON配置框填入同样的registry-mirrors字段保存后Docker Desktop会自动应用并重启引擎。用表格把几个目前还能用的公共mirror地址整理一下你可以根据自己的网络环境尝试国内不同运营商对不同的加速器体验差异还挺大的没有绝对最优的实测为准镜像加速地址特点适用场景https://docker.m.daocloud.io速度均衡社区使用广泛大多数家庭宽带和云服务器https://dockerproxy.com偶尔抽风但高峰期尚可备选方案之一https://docker.nju.edu.cn教育网优化高校效果好校园网、教育网络环境https://hub-mirror.c.163.com网易老牌镜像稳定但更新偏慢老项目拉取常用镜像配置完成之后怎么确认加速器真的生效了拉一个镜像然后在拉取日志里看一下输出地址是否包含了mirror的域名。如果输出还是从registry-1.docker.io下载说明配置没生效回到之前的步骤检查daemon.json是否放在了正确的路径、格式是否是合法的JSON。如果几个镜像地址都不通也不要着急可以过段时间再试公共加速器偶发不可用是很正常的事情最好的解法还是自建一个registry mirror用Nginx反代Docker Hub的registry接口限速和稳定性完全自主可控。不过这个话题展开又是一篇大文章这里先不细说。5.3 daemon.json里值得顺手配置好的几个参数镜像加速只是daemon.json的基础功能。有过线上运维经验的人都知道Docker默认配置里有个大坑容器日志不限制大小。如果一个容器打印日志比较勤快或者出现了异常刷日志短短几天就能把磁盘写满。所以在配置daemon.json的时候我会把日志文件的大小和数量一起限制好{ log-driver: json-file, log-opts: { max-size: 50m, max-file: 3 } }这样每个容器最多保留3个日志文件每个文件最大50MB超过就轮转切割磁盘安全得到了比较基础的保障。配置同样要重启Docker才生效注意它只对新创建的容器生效已经存在的容器需要重建才会应用新日志策略。另一个值得在安装阶段就顺手做的事是在/etc/docker/目录下维护好daemon.json的备份。因为docker的配置史越长越容易出各种奇怪的合成问题而daemon.json就是Docker引擎行为的总开关不夸张地说它决定了引擎的网络模式、存储驱动、镜像加速、日志策略、远程访问开关等一揽子行为。出问题时直接恢复备份往往比花时间排查配置文件要高效得多。5.4 小白的常用验证命令组我不建议安装完成之后立刻进入“拉一大堆镜像跑起来”的状态而是先花两分钟把这条命令链走一遍确认每个环节都正常docker version # 看客户端和服务端版本是否都在线 docker info # 看存储驱动、镜像加速器、逻辑CPU等全局信息 docker run --rm hello-world # 验证基本容器创建能力 docker compose version # 验证Compose插件 docker ps -a # 确认没有异常残留的容器这套命令里docker info的输出信息量最大值得看一眼几个关键字段Server Version、Storage Driver一般是overlay2、Cgroup Driver新版本一般是systemd、Registry Mirrors如果配置了加速器这里会列出来。如果Cgroup Driver显示的是cgroupfs且你的系统使用systemd管理服务建议改成systemd这能避免某些情况下Docker和systemd的cgroup资源管理发生冲突。6. 装完就报错的常见坑从API连接到网络不通的直接解法到了这一步大部分人的Docker环境已经能用了但还有一批人会卡在各种千奇百怪的报错上。我把这些年看得最多的几类报错放在这里每个都给到可以直接照做的排查链路。6.1 Docker Desktop报npipe连接失败怎么办前面在Windows小节已经讲了一段这里补充一个更完整的排查路径。报错信息里出现的npipe:////./pipe/dockerDesktopLinuxEngine本质上是Windows下Docker客户端和引擎之间的IPC通道。失败原因可能是引擎没起来、WSL2状态异常、或者命名管道服务被系统策略禁用。按下列顺序做成功率很高右键托盘鲸鱼图标选择“Restart”等待30秒再看docker version。若不行PowerShell里执行wsl --shutdown等10秒重新打开Docker Desktop。若还不行关闭所有Docker相关进程包括后台服务然后执行wsl --unregister docker-desktop重建Docker Desktop的WSL发行版。最后的手段是在“设置-疑难解答-Clean / Purge data”里重置Docker Desktop但这会清掉本地的所有镜像和容器操作前确认没有需要保留的数据。95%的情况下前两步就能解决。如果你发现自己反复出现这个报错多半是WSL2内核和Docker Desktop版本不匹配执行wsl --update更新WSL内核同时把Docker Desktop更新到最新版本别让两个软件之间差太远。6.2 我一敲docker compose就提示未知命令在前面已经提过unknown command: docker compose的本质是Compose插件缺失。这里给一个完整的验证顺序docker version # 确认Docker CLI版本是否在20.10以上 docker compose version # 确认插件是否存在 ls /usr/libexec/docker/cli-plugins/ # 部分发行版插件放在这个目录 ls /usr/local/lib/docker/cli-plugins/ # 还有可能在这个目录如果你发现插件文件存在但命令还是提示未知大概率是环境变量PATH里Docker插件目录没有被找到。可以在/etc/docker/daemon.json里显式指定CLI插件目录{ cli-plugins-dir: /usr/libexec/docker/cli-plugins }重启shell之后再验证。但更常见的场景其实就是压根没装插件。不记得自己装没装过的话直接执行sudo apt install -y docker-compose-plugin # 或者 sudo yum install -y docker-compose-plugin装完立刻验证这个坑基本就填平了。6.3 容器之间、容器和宿主机之间网络不通“docker网络不通”这个热搜词我怀疑不少人遇到的是同一个困惑容器A能访问外网但访问不了容器B宿主机能docker ps但访问不了某个映射了端口的服务。这类问题的根源通常不是Docker装坏了而是对网络模式的理解有偏差。Docker安装之后默认会创建一个bridge网络所有用默认参数启动的容器都挂在这个网桥上它们之间可以通过IP互访。但是容器重启之后IP会变IP变了就可能导致你记录的访问地址失效。另外如果分别用docker run -p 3306:3306和docker run -p 3307:3306启动两个MySQL容器它们之间如果想要互相联调走的是各自映射在宿主机上的端口而不是容器内部的3306。解法也很简单自己创建一个自定义网络然后把容器都放到这个网络下Docker内置的DNS解析器会自动支持同一个自定义网络内的容器通过容器名互访docker network create app-net docker run -d --network app-net --name mysql8 mysql:8.0 docker run -d --network app-net --name redis redis:7 docker exec -it redis-container redis-cli -h mysql8 ping这样Redis容器里直接就能解析mysql8这个主机名相当于把容器名变成了服务发现地址。在Compose文件里也是一样的逻辑你定义的每个service名称在自定义网络里天然就是可解析的主机名。还有一个常见场景是容器能外网但宿主机访问不了容器映射的端口。这个要先查防火墙Linux上记得放行映射端口比如sudo ufw allow 8080/tcp如果你用的是云服务器那还要检查云安全组是否放行了对应端口。端口映射本身没问题但防火墙把流量拦住了表现为外网访问超时本地localhost访问正常。6.4 我自己的“翻车排查五步法”最后分享一下我处理Docker报错时用的固定套路基本上能覆盖掉八成以上的问题。不管是什么报错先按这个顺序走看状态docker ps -a、docker compose ps、systemctl status docker确认是引擎问题还是容器问题。看日志docker logs --tail 200 container绝大多数容器问题都在日志里写得明明白白。看端口ss -tlnp | grep 端口确认端口真的被监听了再考虑防火墙和云安全组。看资源free -h、df -h、docker system df看看是不是内存、磁盘、镜像缓存耗尽了。日志爆盘、内存OOM导致容器被杀都是运维里非常常见的事故。重启降级docker compose restart或者docker restart甚至极端情况下重启Docker守护进程很多临时性的网络和文件句柄问题都能被这一招清掉。这个套路没有什么高深的理论但非常实用。排查问题最忌瞎试按顺序确认每一步基本都能定位到具体环节。这里顺带提醒一个非常冷门但常见的坑某些Linux服务器上Docker引擎启动之后docker ps命令能正常输出但容器无法创建报iptables相关错误。这往往是因为宿主机上的iptables规则被其他程序覆盖了比如firewalld。此时可以把Docker的iptables操作能力关闭在daemon.json里设置iptables: false但关闭之前要意识到这会影响端口映射和容器网络隔离只适合在纯开发环境里这么干。生产环境还是要梳理好防火墙和Docker的共存关系。装Docker这件事说难不难说简单也不简单。难点从来不在Docker本身而在于你对宿主环境有没有足够的预判。我在实际部署中最大的体会是安装方案的核心不是“敲几条命令”而是“让引擎和宿主环境达成一致”。WSL2没配对、内核版本过老、Compose插件缺失、镜像源没配好、权限组没加入任何一个环节没对上后面都会以各种奇怪的形式反噬你。所以这篇安装方案里我特意把验证和排错放在了和安装同等重要的位置在你准备把Docker塞进日常工具箱之前先花十分钟把这些底子打好之后整个世界都会清净很多。
返回列表