Docker常见故障全方位排查指南

凌晨线上容器集体 Exited,我冲上去连敲 docker ps 都没有反应,折腾半小时才发现根因根本不在容器,而在守护进程。

这篇把 Docker 排查收敛成一条决策链路,从报错到根因,照着走就行。

一、docker ps 都没反应:问题在守护进程

容器挂了,你登录主机敲下 docker ps,终端没有列出任何容器,反而甩回这么一句:

latex 复制代码
Cannot connect to the Docker daemon at unix:///var/run/docker.sock.
Is the docker daemon running?

这句报错和容器本身没有任何关系。Docker 采用客户端/服务器架构,docker 命令只是客户端,真正管理容器、镜像的是后台的守护进程(dockerd),二者通过本地套接字 /var/run/docker.sock 通信。连不上守护进程,只有两种可能:进程没启动,或者当前用户没有权限访问套接字。

报错根因 典型现象 处理方式
守护进程未启动 重启机器或服务异常后,所有命令无响应 启动并设置开机自启
当前用户无权限 普通用户执行命令报权限相关错误 把用户加入 docker 用户组

对应的修复命令:

bash 复制代码
systemctl status docker
systemctl start docker
systemctl enable docker
usermod -aG docker $USER
newgrp docker

如果你执行 systemctl start docker 后服务状态直接是 failed,说明守护进程没起来,常见诱因是 /etc/docker/daemon.json 配置语法错误或存储驱动不匹配。这时不要反复重启,直接看守护进程日志定位:

bash 复制代码
journalctl -u docker -xe

修复配置后重新 systemctl restart docker,再用 docker info 验证:能正常打印版本、存储驱动、容器数量等信息,就说明守护进程已经恢复。

注意:docker info 是验证守护进程是否真正可用的最快方式,比 systemctl status 更可信。

守护进程通了,docker ps 也有输出了,可你 docker run 启动一个新容器时,却报端口冲突、容器名冲突、OCI 运行时失败,甚至容器瞬间 Exited,这四种情况怎么分?

二、容器起不来问题排查

容器启动失败看似报错五花八门,实则只有四道门。先按报错关键字分流,再用对应命令取证:

报错关键字 根因 第一手取证命令
port is already allocated 宿主机端口被其他进程或容器占用 ss / lsof
name already in use 同名容器已存在(多为停止状态) docker ps -a
OCI runtime create failed 权限、SELinux、挂载、cgroup 等系统级问题 docker inspect / journalctl
Exited (1) 容器内主进程启动失败后退出 docker logs

第一道:端口被占用。映射端口前,先查是谁占用了它:

bash 复制代码
ss -tulnp | grep 8080
lsof -i:8080

找到占用进程后,停掉冲突进程,或把容器映射到其他端口(如 -p 8081:80)。

第二道:容器名冲突。同名容器即使已经停止,名字仍然被占用,删掉旧容器即可:

bash 复制代码
docker ps -a
docker rm 旧容器名或容器ID

第三道:运行时创建失败。这是系统级问题,重点看挂载路径和安全策略。用 docker inspect 查看容器完整配置,用 journalctl 查看守护进程记录的底层拒绝信息:

bash 复制代码
docker inspect 容器ID
journalctl -u docker -xe

第四道:启动即退出。docker run 明明返回成功,容器状态却是 Exited (1)。我第一次遇到时只会反复 docker run,每次都瞬间退出,后来才明白停止的容器进不去,唯一的现场就是日志:

bash 复制代码
docker ps -a
docker logs --tail 200 容器名或容器ID
docker logs -f --tail 200 容器名或容器ID

容器的生命周期与主进程绑定:主进程在,容器在;主进程退出,容器随之停止。 所以 Exited 的根因永远在主进程的启动日志里,而不是 Docker 本身。

处理完后用 docker ps 验证,目标容器状态为 Up 即通过。

容器能起了,可换台机器、或重新拉取镜像时,docker pull 直接卡死或报拒绝,连镜像都没有,容器从何而来?

三、镜像拉不下来:问题集中在认证、网络、架构

镜像(Image)是容器的只读模板,拉取失败集中在认证、网络、架构三类,先按报错关键字对号入座:

报错关键字 根因 处理方式
pull access denied / manifest unknown 私有仓库未登录,或标签(tag)写错 docker login,核对镜像名与标签
TLS handshake timeout / connection refused 网络波动、加速器失效、代理异常 配置镜像加速器或代理
exec format error 镜像架构与宿主机不匹配 指定平台参数运行

认证类问题,先登录私有仓库,再核对镜像名和标签是否真实存在:

bash 复制代码
docker login registry.example.com
docker pull nginx:1.25
docker logout registry.example.com

网络类问题,在 /etc/docker/daemon.json 中配置镜像加速器,然后重启守护进程生效:

json 复制代码
{
  "registry-mirrors": ["https://你的加速器地址"]
}
bash 复制代码
systemctl daemon-reload
systemctl restart docker

架构类问题,我在一台 ARM64 主机上跑 AMD64 镜像时栽过,CPU 指令集不兼容,启动即报 exec format error。跨架构运行时用 --platform 显式指定架构:

bash 复制代码
docker run --platform linux/amd64 nginx:1.25

还有一类不是报错、而是慢:每次 docker build 都全量重新下载依赖,分层缓存完全失效。镜像由多个只读层(layer)堆叠而成,构建时逐层命中缓存。Dockerfile 中任意一层发生变更,其后所有层的缓存全部失效。 因此依赖安装必须放在业务代码拷贝之前,并用 .dockerignore 排除无关文件:

dockerfile 复制代码
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
CMD ["node", "server.js"]

把 package.json 单独提前 COPY,业务代码变更不会再让依赖层缓存失效,这是构建提速最直接的一步。

用 docker images 验证目标镜像与标签存在,即拉取或构建完成。

镜像有了、容器也 Up 了,可 curl 过去要么超时、要么 502,容器之间还互相 ping 不通,这网络怎么查?

四、容器活着但不通:容器间、宿主机、DNS

Docker 网络问题可以收敛为三件事,逐一排查:

故障现象 根因 处理方式
容器间 ping 容器名报 bad address 默认桥接网络(bridge)隔离,不提供容器名解析 改用自定义桥接网络
宿主机访问不了容器 端口映射未生效、服务只监听 127.0.0.1、防火墙拦截 核对映射、监听地址、防火墙
容器内域名解析失败 默认 DNS 异常 指定 DNS 或全局配置

容器之间默认都接入名为 bridge 的默认网络,该网络下容器彼此隔离,也不能通过容器名互访。创建一个自定义桥接网络,把相关容器都接进去:

bash 复制代码
docker network create mynet
docker run -d --network mynet --name app nginx:1.25
docker run -d --network mynet --name db mysql:8.0

同一自定义网络内,容器可直接通过容器名互相访问,Docker 会自动维护容器名到 IP 的域名解析(DNS)。 之后 app 连接 db 直接用容器名即可,无需写死 IP。

宿主机访问不了容器时,先确认映射和服务监听地址。服务若只监听容器内的 127.0.0.1,宿主机和其他容器都无法访问,必须监听 0.0.0.0:

bash 复制代码
docker ps
docker exec -it 容器ID netstat -tulnp

容器内无法解析外网域名(Name or service not known),可以在启动时指定公共 DNS 临时验证,再决定是否写入守护进程全局配置:

bash 复制代码
docker run -d --dns 8.8.8.8 nginx:1.25

验证方式:进入一个容器 ping 同网络的另一个容器名,能通则容器间网络正常。

网络通了,业务却开始报 Permission denied、写文件失败,甚至整个节点磁盘写满,这些"看不见"的存储问题怎么处理?

五、写不进去、磁盘爆满:存储与权限

存储类问题没有统一报错位置,先按现象归为三类:

故障现象 根因 处理方式
挂载目录 Permission denied 容器内用户 UID/GID 与宿主机目录权限不一致 chown 或 --user 指定用户
挂载后容器内文件全部消失 空目录绑定挂载(bind mount)遮蔽了容器目录 改用命名卷,或先复制文件
no space left on device 废弃镜像、容器、缓存、日志占满磁盘 查看占用并清理

权限拒绝,本质是容器内进程的用户身份和宿主机目录归属对不上。把宿主机目录归属改成容器内用户的 UID/GID,或启动时直接指定运行用户:

bash 复制代码
chown -R 1000:1000 /data
docker run -d --user 1000:1000 -v /data:/container/data nginx:1.25

把宿主机空目录挂载到容器内非空目录时,容器目录里镜像自带的配置文件不会被删除,但会被宿主机目录整体遮蔽,看起来就是"文件全没了"。绑定挂载会用宿主机目录原样遮蔽容器目录,镜像内文件不会自动复制出来。 更稳妥的做法是使用命名卷(named volume),由 Docker 管理数据,首次挂载时还会自动把容器目录内容拷入卷中:

bash 复制代码
docker volume create myvol
docker run -d -v myvol:/container/data nginx:1.25

磁盘写满,先看清空间被谁占用,再决定清理范围:

bash 复制代码
docker system df
docker system prune -a
docker volume prune

注意:<font style="color:#c00;">docker system prune -a</font> 会删除所有未被运行容器使用的镜像,生产环境执行前务必确认镜像可重新拉取,避免误删。

容器日志也会持续膨胀,路径为 /var/lib/docker/containers/*/*-json.log,需要纳入定期清理。清理后用 docker system df 验证空间已回收。

零散命令临时记不住,有没有一套固定打法?

六、通用命令速查

下面这九条命令覆盖了绝大多数取证场景,建议直接收藏:

bash 复制代码
docker ps -a
docker logs -f --tail 200 容器名或容器ID
docker inspect 容器名或容器ID
docker exec -it 容器名或容器ID sh
docker stats
docker events
docker system df
docker info
journalctl -u docker -xe

排查闭环始终是同一条路径:

latex 复制代码
现象  ->  日志  ->  定位  ->  修复  ->  验证
 |          |         |
报错截图  logs/journalctl  对照本文表格分流

术语速查表:

术语 英文 含义
镜像 Image 容器的只读模板,含运行所需文件
容器 Container 镜像运行后的实例,生命周期随主进程
守护进程 dockerd 后台服务,管理镜像、容器、网络、存储
标签 tag 镜像的版本标记,如 nginx:1.25
分层 layer 镜像由多层只读层堆叠,支撑构建缓存
桥接网络 bridge Docker 默认网络驱动,默认网络下容器隔离
域名解析 DNS 将容器名或域名解析为 IP
绑定挂载 bind mount 把宿主机目录直接挂载进容器
命名卷 named volume 由 Docker 管理的数据卷
用户标识 UID/GID 进程的用户与用户组编号,决定文件权限

结语

排查 Docker 故障,顺序不能乱,越往下越靠近业务内层------先确认命令能不能用(守护进程),再看容器能不能起(四道门),然后是镜像能不能拉(三道关)、网络通不通(三件事)、数据对不对(存储)。绝大多数问题不需要深入调试,按报错关键字分流、用对应命令取证,就能快速定位。

参考链接(均为 Docker 官方文档):

相关推荐
谢亮_vipxieliang1 小时前
云原生存储进阶:CSI 演进与 AI 工作负载的存储架构设计
人工智能·云原生
木子欢儿1 小时前
Zabbix 7.4 Alpine 版 Docker Compose 部署
android·运维·docker·容器·zabbix
朱包林1 小时前
iTerm2终端配置指南
linux·javascript·python·云原生·容器·kubernetes·云计算
pengdott1 小时前
Rocky linux9安装Jenkins最新版本2.585
运维·jenkins·流水线
祖力552 小时前
Linux系统移植、烧录与环境的搭建
linux·运维·服务器
对讲机数码科普2 小时前
从电路原理到协议栈:模拟对讲机与数字对讲机的技术内核拆解
运维·网络·架构·软件工程
打工仔折腾 AI2 小时前
极空间用 Docker 部署 Photopea:网页版 PS 的私有化实践
运维·后端·python·docker·容器·langchain·ai agent 实战
工具人55552 小时前
Docker 最新超详细版教程
运维·docker·容器
Wang's Blog2 小时前
Java 项目部署之 Docker工具快速入门: 使用 Docker 镜像命令练习
java·docker