Skip to content

Docker 排障:构建、退出、网络与存储 · 容器退出、网络与存储排障 ​

返回分篇目录

容器退出、网络与存储排障 ​

本节沿容器日志、UPSTREAM 和实际挂载定位失败层;先确认Context、store/gateway、项目名与 counter 卷,与配套示例逐项对照,再选择最小修复。

先保留证据 ​

Docker 故障 证据 包括项目名、Context、镜像引用、容器创建时间、退出状态、健康检查输出、日志和最近变更。先明确受影响的是构建、创建、进程启动、监听还是业务请求,再选下一条检查。本文只列未来诊断方法。

inspect 可能包含环境变量和宿主路径;日志也可能含业务数据。保存时按事故流程脱敏,不把完整配置公开粘贴。重启可能清掉退出前时序,删除容器可能丢失可写层;先保存可用证据再讨论恢复动作。

构建失败与平台不匹配 ​

Docker COPY 失败 优先核对构建上下文与 .dockerignore,而不是立即 --no-cache。主例从 examples/m5-docker 构建,COPY app.py 位于该上下文;从仓库根构建会改变输入集合。RUN 非零退出需看该指令的完整错误、网络与权限。exec format error 常指 CPU 架构或解释器格式,不应通过改 bridge 网络来修复。

退出与 OOM ​

Docker 退出 137 不是 OOM 的充分证据。137 通常按 128+9 对应 SIGKILL,但来源仍需证据。收集 ExitCode、OOMKilled、Error、StartedAt/FinishedAt,并对齐宿主事件;启动命令不存在、用户无权限、挂载失败与内存耗尽需要不同修复。主例 token 不存在不会影响 Docker 项目,因为主例不读取 token;不要把 Kubernetes 示例的配置假设套过来。

容器不停重启时先区分应用主动退出与重启策略的结果。健康检查 unhealthy 但主进程仍运行是正常可能状态;Docker Engine 的普通 healthcheck 不会据此自动重启。

能解析但连接失败 ​

Docker 连接拒绝 要分开看名字解析、容器端口与应用监听。gateway 的 UPSTREAM 应为 http://store:8080,宿主 18080 不能用作容器间服务端口。DNS 成功只说明获得地址,不证明端口有人监听;监听成功也不证明数据库就绪。

若宿主请求失败而同网络请求正常,再看 ports、回环绑定、防火墙和 VM 转发。若 /live 正常但 /ready 503,检查依赖与数据库,而不是把 liveness 改成依赖全链路导致重启放大故障。

权限与数据丢失假象 ​

Docker Permission denied 常由 UID/GID、只读挂载或 Linux LSM 决定,chmod 777 不能解释根因,也不应关闭宿主安全策略试运气。镜像里 chown /data 不会修复已有卷内容;bind mount 更不会继承镜像目录权限。

计数归零先核对 Compose 项目名、卷挂载目标、实际卷名和是否曾 down --volumes,再判断是否需要恢复。不要因为看到了新卷就删除旧卷;旧卷可能保存唯一恢复副本。

诊断练习与解答 ​

题目:store healthy,gateway unhealthy,宿主收到 503,最小假设是什么?答案:先检查 gateway 的 UPSTREAM 与请求日志,确认它是否以服务名访问容器端口;store 的健康只证明本地数据库读成功,不证明 gateway 的配置正确。每次只修一个变量,再回到原请求确认。

题目:137 且 OOMKilled=false 可以断言什么?答案:只能缩小到强制终止相关路径,仍需检查人工 kill、停止超时与宿主故障;不能仅加大内存。

原有故障手册保留构建和退出场景的完整步骤;本课补上每一步要证伪的假设。

代理、AppArmor 与网络规则的证据边界 ​

Docker 代理不生效和 AppArmor permission denied 应先区分哪些边界? 拉镜像失败先判断请求来自哪个进程。旧记录把代理写进 docker.service 的 systemd drop-in,这针对 daemon;终端 HTTP_PROXY、容器环境变量和 daemon 代理分别作用于不同请求路径。核对 Engine 的代理配置来源及 NO_PROXY 排除目标,避免把内部 Registry 也绕到外部代理。配置方式还受 Engine/Desktop 平台差异约束,不能原封不动复制旧机器的 Group、私网代理地址或带错误引号的 NO_PROXY。daemon 代理官方说明已于 2026-10-17 核对。

停止容器时出现 permission denied,要区分 Docker socket 访问、容器内 UID/GID 与 AppArmor 拒绝。旧文 aa-remove-unknown 和 chmod 666 docker.sock 是不同权限层的修改,不能由一个错误字符串推导都应执行。先保留完整错误、运行时/daemon 日志和内核拒绝记录,再定位策略或身份;对 AppArmor 以实际 profile 和审计记录为证据,官方排障说明不支持无证据移除安全边界。旧 exit status 41 也不能单凭文本确诊内存耗尽,drop_caches 不是诊断结论。

SKIP DNAT 失败应把防火墙变更、Docker 网络规则与 daemon 时序放在同一时间线,不能把“重启后恢复”写成普适根因。日志先从 logs 与 inspect 提供的状态定位,历史 LogPath 是具体驱动和容器的内部位置;不要把路径复制到另一主机,也不要直接删除内部日志恢复服务。本节不执行重启、缓存清理或规则变更。

继续阅读