Docker故障排查

一、故障排查概述

1.1 故障排查方法论

1.1.1 故障排查流程

系统化排查流程:

┌─────────────────────────────────────────┐
│         故障排查流程                     │
├─────────────────────────────────────────┤
│                                         │
│  1. 问题识别                            │
│     ├─ 收集故障信息                     │
│     ├─ 确认故障现象                     │
│     └─ 评估影响范围                     │
│                                         │
│  2. 问题分析                            │
│     ├─ 查看日志                         │
│     ├─ 检查配置                         │
│     ├─ 检查资源                         │
│     └─ 检查网络                         │
│                                         │
│  3. 问题定位                            │
│     ├─ 分析根本原因                     │
│     ├─ 确认故障点                       │
│     └─ 制定解决方案                     │
│                                         │
│  4. 问题解决                            │
│     ├─ 实施解决方案                     │
│     ├─ 验证修复效果                     │
│     └─ 监控系统状态                     │
│                                         │
│  5. 问题总结                            │
│     ├─ 记录故障原因                     │
│     ├─ 总结经验教训                     │
│     └─ 制定预防措施                     │
└─────────────────────────────────────────┘

东巴文理解:

故障排查思维:
┌──────────────────┬──────────────┬──────────────┐
│     排查阶段     │   关键动作   │   常用工具   │
├──────────────────┼──────────────┼──────────────┤
│  问题识别       │ 收集信息     │ docker ps    │
│  问题分析       │ 查看日志     │ docker logs  │
│  问题定位       │ 检查配置     │ docker inspect│
│  问题解决       │ 实施修复     │ docker exec  │
│  问题总结       │ 文档记录     │ 文档系统     │
└──────────────────┴──────────────┴──────────────┘

故障排查原则:
├─ 由简到繁: 先检查简单问题
├─ 由外到内: 先检查外部因素
├─ 分层排查: 网络→存储→应用
├─ 对比验证: 对比正常与异常
└─ 文档记录: 记录排查过程

1.1.2 故障分类

常见故障类型:

容器故障:
├─ 容器无法启动
├─ 容器频繁重启
├─ 容器运行异常
└─ 容器无法停止

镜像故障:
├─ 镜像拉取失败
├─ 镜像构建失败
├─ 镜像过大
└─ 镜像损坏

网络故障:
├─ 容器无法访问
├─ 网络连接超时
├─ DNS解析失败
└─ 端口冲突

存储故障:
├─ 数据卷挂载失败
├─ 磁盘空间不足
├─ IO性能问题
└─ 数据丢失

资源故障:
├─ CPU使用过高
├─ 内存不足
├─ 磁盘IO瓶颈
└─ 网络带宽不足

守护进程故障:
├─ Docker服务无法启动
├─ Docker命令无响应
├─ 权限问题
└─ 配置错误

1.2 故障排查工具

1.2.1 Docker内置工具

基本排查命令:

# 查看容器状态
docker ps -a

# 输出
CONTAINER ID   IMAGE         COMMAND    CREATED       STATUS                     PORTS     NAMES
a1b2c3d4e5f6   nginx         "nginx"    2 hours ago   Exited (1) 5 minutes ago             nginx

# 查看容器日志
docker logs nginx

# 查看容器详情
docker inspect nginx

# 查看容器资源使用
docker stats nginx

# 查看容器进程
docker top nginx

# 查看容器端口映射
docker port nginx

# 查看容器网络
docker network ls
docker network inspect bridge

# 查看容器存储
docker volume ls
docker volume inspect mydata

# 查看Docker系统信息
docker info

# 查看Docker版本
docker version

# 查看Docker事件
docker events

日志查看技巧:

# 查看最近100行日志
docker logs --tail 100 nginx

# 实时查看日志
docker logs -f nginx

# 查看指定时间段的日志
docker logs --since 2024-01-01T00:00:00 nginx
docker logs --until 2024-01-01T12:00:00 nginx

# 查看最近1小时的日志
docker logs --since 1h nginx

# 查看带时间戳的日志
docker logs -t nginx

# 导出日志到文件
docker logs nginx > /tmp/nginx.log 2>&1

1.2.2 系统工具

系统排查工具:

# 查看系统资源
top
htop
free -h
df -h

# 查看网络连接
netstat -tulnp
ss -tulnp

# 查看进程
ps aux | grep docker

# 查看系统日志
journalctl -u docker

# 查看内核日志
dmesg | grep docker

# 查看系统负载
uptime

# 查看IO状态
iostat -x 1

# 查看网络流量
iftop
nethogs

# 查看文件描述符
lsof -p <pid>

# 查看系统调用
strace -p <pid>

# 查看网络包
tcpdump -i docker0 -nn

二、容器故障排查

2.1 容器启动失败

2.1.1 常见启动失败原因

启动失败原因分析:

容器启动失败常见原因:
┌──────────────────┬──────────────┬──────────────┐
│     原因类型     │   现象       │   解决方法   │
├──────────────────┼──────────────┼──────────────┤
│  镜像不存在     │ 镜像拉取失败  │ 拉取或构建镜像│
│  配置错误       │ 参数错误      │ 检查配置     │
│  端口冲突       │ 端口被占用    │ 更换端口     │
│  资源不足       │ OOM           │ 增加资源     │
│  权限问题       │ 权限拒绝      │ 调整权限     │
│  依赖服务       │ 依赖未启动    │ 启动依赖     │
│  存储问题       │ 挂载失败      │ 检查存储     │
│  网络问题       │ 网络配置错误  │ 检查网络     │
└──────────────────┴──────────────┴──────────────┘

排查步骤:

# 1. 查看容器状态
docker ps -a | grep nginx

# 输出
CONTAINER ID   IMAGE         COMMAND    CREATED       STATUS                     PORTS     NAMES
a1b2c3d4e5f6   nginx         "nginx"    2 hours ago   Exited (1) 5 minutes ago             nginx

# 2. 查看容器日志
docker logs nginx

# 输出
2024-01-01T00:00:00.000000000Z nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)

# 3. 查看容器详情
docker inspect nginx

# 输出
[
    {
        "Id": "a1b2c3d4e5f6...",
        "State": {
            "Status": "exited",
            "ExitCode": 1,
            "Error": "",
            "StartedAt": "2024-01-01T00:00:00.000000000Z",
            "FinishedAt": "2024-01-01T00:00:05.000000000Z"
        }
    }
]

# 4. 检查镜像
docker images nginx

# 5. 检查端口占用
netstat -tulnp | grep :80

# 输出
tcp6       0      0 :::80                 :::*                    LISTEN      1234/docker-proxy

2.1.2 启动失败解决方案

镜像问题:

# 镜像不存在
docker pull nginx:latest

# 镜像损坏
docker rmi nginx:latest
docker pull nginx:latest

# 镜像标签错误
docker pull nginx:1.21.0

# 镜像仓库访问失败
# 配置镜像加速器
# /etc/docker/daemon.json
{
  "registry-mirrors": [
    "https://mirror.ccs.tencentyun.com"
  ]
}

# 重启Docker
systemctl restart docker

配置问题:

# 参数错误
# 检查启动参数
docker inspect --format '{{.Config.Cmd}}' nginx

# 环境变量错误
docker inspect --format '{{.Config.Env}}' nginx

# 工作目录错误
docker inspect --format '{{.Config.WorkingDir}}' nginx

# 用户错误
docker inspect --format '{{.Config.User}}' nginx

# 重新启动容器
docker rm nginx
docker run -d --name nginx nginx:latest

端口冲突:

# 查看端口占用
netstat -tulnp | grep :80

# 停止占用端口的容器
docker stop <container_id>

# 更换端口
docker run -d --name nginx -p 8080:80 nginx:latest

# 查看端口映射
docker port nginx

资源不足:

# 查看系统资源
free -h
df -h

# 查看容器资源限制
docker inspect --format '{{.HostConfig.Memory}}' nginx

# 增加资源限制
docker update --memory="1g" nginx

# 清理无用资源
docker system prune -a

2.2 容器运行异常

2.2.1 容器频繁重启

排查容器重启原因:

# 查看容器重启次数
docker inspect --format '{{.RestartCount}}' nginx

# 查看重启策略
docker inspect --format '{{.HostConfig.RestartPolicy.Name}}' nginx

# 查看容器退出码
docker inspect --format '{{.State.ExitCode}}' nginx

# 查看容器日志
docker logs --tail 100 nginx

# 查看系统日志
journalctl -u docker | grep nginx

# 查看OOM事件
dmesg | grep -i "Out of memory"

常见重启原因:

容器重启原因:
┌──────────────────┬──────────────┬──────────────┐
│     退出码      │   含义       │   解决方法   │
├──────────────────┼──────────────┼──────────────┤
│  0              │ 正常退出      │ 检查应用逻辑 │
│  1              │ 应用错误      │ 查看应用日志 │
│  137            │ OOM Killed    │ 增加内存     │
│  139            │ 段错误        │ 检查应用代码 │
│  143            │ SIGTERM       │ 正常停止     │
│  255            │ 退出码超范围  │ 检查应用代码 │
└──────────────────┴──────────────┴──────────────┘

重启策略:
├─ no: 不自动重启
├─ on-failure: 失败时重启
├─ always: 总是重启
└─ unless-stopped: 除非手动停止

解决方案:

# OOM问题
# 增加内存限制
docker update --memory="2g" nginx

# 应用错误
# 查看应用日志
docker logs -f nginx

# 进入容器调试
docker exec -it nginx sh

# 健康检查失败
# 检查健康检查配置
docker inspect --format '{{.Config.Healthcheck}}' nginx

# 手动执行健康检查
docker exec nginx curl -f http://localhost/ || exit 1

# 调整重启策略
docker update --restart=on-failure:5 nginx

2.2.2 容器性能问题

性能问题排查:

# 查看容器资源使用
docker stats nginx

# 输出
CONTAINER ID   NAME      CPU %     MEM USAGE / LIMIT     MEM %     NET I/O           BLOCK I/O         PIDS
a1b2c3d4e5f6   nginx     85.50%    512.5MiB / 1GiB      50.05%    15.2MB / 8.5MB    100MB / 50MB      5

# 查看容器进程
docker top nginx

# 输出
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                12345               12340               0                   00:00               ?                   00:00:00            nginx: master process
101                 12346               12345               85                  00:00               ?                   00:05:00            nginx: worker process

# 查看容器内进程详情
docker exec nginx ps aux

# 查看系统调用
strace -p 12346

# 查看网络连接
docker exec nginx netstat -tulnp

# 查看文件描述符
docker exec nginx lsof -p 1

性能优化:

# CPU性能优化
docker update --cpus="2.0" nginx

# 内存性能优化
docker update --memory="2g" nginx

# IO性能优化
docker update --blkio-weight=700 nginx

# 网络性能优化
docker network create --driver bridge --opt com.docker.network.driver.mtu=1500 mynetwork
docker network connect mynetwork nginx

2.3 容器无法停止

2.3.1 容器停止问题

排查停止问题:

# 尝试停止容器
docker stop nginx

# 超时后强制停止
docker stop -t 10 nginx

# 强制停止容器
docker kill nginx

# 查看容器状态
docker inspect --format '{{.State.Status}}' nginx

# 查看容器进程
docker top nginx

# 查看容器PID
docker inspect --format '{{.State.Pid}}' nginx

# 查看进程状态
ps -p <pid> -o pid,ppid,stat,cmd

# 查看进程状态码
# D: 不可中断睡眠
# S: 睡眠
# R: 运行
# Z: 僵尸进程

解决方案:

# 1. 正常停止
docker stop nginx

# 2. 强制停止
docker kill nginx

# 3. 发送SIGTERM信号
kill -TERM <pid>

# 4. 发送SIGKILL信号
kill -KILL <pid>

# 5. 重启Docker服务
systemctl restart docker

# 6. 删除容器
docker rm -f nginx

# 7. 查看僵尸进程
ps aux | grep Z

# 8. 清理僵尸进程
# 需要重启主机

三、镜像故障排查

3.1 镜像拉取失败

3.1.1 拉取失败原因

常见拉取失败原因:

镜像拉取失败原因:
┌──────────────────┬──────────────┬──────────────┐
│     原因类型     │   现象       │   解决方法   │
├──────────────────┼──────────────┼──────────────┤
│  网络问题       │ 连接超时      │ 检查网络     │
│  认证问题       │ 权限拒绝      │ 登录认证     │
│  镜像不存在     │ 镜像未找到    │ 检查镜像名   │
│  磁盘空间不足   │ 空间不足      │ 清理空间     │
│  仓库访问限制   │ 访问受限      │ 使用镜像加速 │
│  DNS解析失败    │ 域名解析失败  │ 配置DNS     │
└──────────────────┴──────────────┴──────────────┘

排查步骤:

# 1. 尝试拉取镜像
docker pull nginx:latest

# 错误信息
Error response from daemon: Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)

# 2. 检查网络连接
ping -c 4 registry-1.docker.io

# 3. 检查DNS解析
nslookup registry-1.docker.io

# 4. 检查磁盘空间
df -h

# 5. 检查Docker配置
cat /etc/docker/daemon.json

# 6. 查看Docker日志
journalctl -u docker | grep pull

3.1.2 拉取失败解决方案

网络问题:

# 配置镜像加速器
# /etc/docker/daemon.json
{
  "registry-mirrors": [
    "https://mirror.ccs.tencentyun.com",
    "https://docker.mirrors.ustc.edu.cn",
    "https://hub-mirror.c.163.com"
  ]
}

# 重启Docker
systemctl restart docker

# 验证配置
docker info | grep "Registry Mirrors" -A 5

# 使用代理
# /etc/systemd/system/docker.service.d/http-proxy.conf
[Service]
Environment="HTTP_PROXY=http://proxy.example.com:8080"
Environment="HTTPS_PROXY=http://proxy.example.com:8080"
Environment="NO_PROXY=localhost,127.0.0.1"

# 重启Docker
systemctl daemon-reload
systemctl restart docker

认证问题:

# 登录Docker Hub
docker login

# 输出
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: yourusername
Password: 
Login Succeeded

# 登录私有仓库
docker login registry.example.com

# 查看认证信息
cat ~/.docker/config.json

# 退出登录
docker logout

磁盘空间问题:

# 查看磁盘使用
df -h

# 查看Docker磁盘使用
docker system df

# 输出
TYPE                TOTAL               ACTIVE              SIZE                RECLAIMABLE
Images              15                  10                  5.5GB               2.5GB (45%)
Containers          20                  15                  1.2GB               500MB (41%)
Local Volumes       10                  8                   800MB               300MB (37%)
Build Cache         50                  0                   2.1GB               2.1GB (100%)

# 清理无用资源
docker system prune -a

# 清理所有未使用的镜像
docker image prune -a

# 清理所有未使用的容器
docker container prune

# 清理所有未使用的卷
docker volume prune

3.2 镜像构建失败

3.2.1 构建失败原因

常见构建失败原因:

镜像构建失败原因:
┌──────────────────┬──────────────┬──────────────┐
│     原因类型     │   现象       │   解决方法   │
├──────────────────┼──────────────┼──────────────┤
│  Dockerfile错误 │ 语法错误      │ 检查Dockerfile│
│  基础镜像问题   │ 镜像不存在    │ 更换基础镜像 │
│  网络问题       │ 下载失败      │ 检查网络     │
│  文件不存在     │ 文件未找到    │ 检查文件路径 │
│  权限问题       │ 权限拒绝      │ 调整权限     │
│  磁盘空间不足   │ 空间不足      │ 清理空间     │
└──────────────────┴──────────────┴──────────────┘

排查步骤:

# 1. 查看Dockerfile
cat Dockerfile

# 2. 构建镜像
docker build -t myapp:v1.0 .

# 错误信息
Step 3/10 : RUN apt-get update
 ---> Running in a1b2c3d4e5f6
Err:1 http://archive.ubuntu.com/ubuntu bionic InRelease
  Could not connect to archive.ubuntu.com:80 (91.189.88.142).
connect (111: Connection refused)

# 3. 使用--no-cache重新构建
docker build --no-cache -t myapp:v1.0 .

# 4. 使用--progress=plain查看详细输出
docker build --progress=plain -t myapp:v1.0 .

# 5. 检查构建缓存
docker builder prune

3.2.2 构建失败解决方案

Dockerfile错误:

# 错误示例
FROM ubuntu:18.04
RUN apt-get update
RUN apt-get install -y nginx
COPY app /app
CMD ["nginx"]

# 正确示例
FROM ubuntu:18.04

# 更新软件源
RUN apt-get update && \
    apt-get install -y nginx && \
    rm -rf /var/lib/apt/lists/*

# 复制应用文件
COPY app /app

# 暴露端口
EXPOSE 80

# 启动命令
CMD ["nginx", "-g", "daemon off;"]

网络问题:

# 使用国内软件源
FROM ubuntu:18.04

# 更换软件源
RUN sed -i 's/archive.ubuntu.com/mirrors.aliyun.com/g' /etc/apt/sources.list && \
    apt-get update && \
    apt-get install -y nginx && \
    rm -rf /var/lib/apt/lists/*

COPY app /app
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

权限问题:

# 使用root用户
USER root

# 或者使用sudo
RUN sudo apt-get update

# 或者修改文件权限
RUN chmod +x /app/start.sh

四、网络故障排查

4.1 网络连接问题

4.1.1 容器网络不通

排查网络问题:

# 1. 查看容器网络
docker network ls

# 输出
NETWORK ID     NAME      DRIVER    SCOPE
a1b2c3d4e5f6   bridge    bridge    local
b2c3d4e5f6a7   host      host      local
c3d4e5f6a7b8   none      null      local

# 2. 查看容器网络配置
docker inspect --format '{{.NetworkSettings.Networks}}' nginx

# 3. 查看容器IP地址
docker inspect --format '{{.NetworkSettings.IPAddress}}' nginx

# 4. 进入容器测试网络
docker exec -it nginx sh

# 在容器内测试
ping -c 4 8.8.8.8
ping -c 4 www.baidu.com
curl -I http://www.baidu.com

# 5. 从主机测试容器
ping -c 4 <container_ip>
curl -I http://<container_ip>:80

# 6. 查看网络接口
docker exec nginx ifconfig

# 7. 查看路由表
docker exec nginx route -n

# 8. 查看DNS配置
docker exec nginx cat /etc/resolv.conf

常见网络问题:

网络问题分类:
┌──────────────────┬──────────────┬──────────────┐
│     问题类型     │   现象       │   解决方法   │
├──────────────────┼──────────────┼──────────────┤
│  无IP地址       │ IP为空        │ 检查网络配置 │
│  DNS解析失败    │ 域名无法解析  │ 配置DNS     │
│  端口不通       │ 无法访问端口  │ 检查防火墙   │
│  网络隔离       │ 容器间不通    │ 配置网络     │
│  MTU问题        │ 大包不通      │ 调整MTU     │
└──────────────────┴──────────────┴──────────────┘

4.1.2 网络问题解决方案

无IP地址问题:

# 查看容器网络模式
docker inspect --format '{{.HostConfig.NetworkMode}}' nginx

# 如果是none模式,连接到网络
docker network connect bridge nginx

# 如果是host模式,容器没有独立IP
# host模式使用主机网络

# 重新创建容器
docker rm -f nginx
docker run -d --name nginx --network bridge nginx:latest

# 查看网络配置
docker network inspect bridge

DNS解析问题:

# 配置DNS服务器
docker run -d \
  --name nginx \
  --dns 8.8.8.8 \
  --dns 8.8.4.4 \
  nginx:latest

# 配置DNS搜索域
docker run -d \
  --name nginx \
  --dns-search example.com \
  nginx:latest

# 使用主机DNS
docker run -d \
  --name nginx \
  --network host \
  nginx:latest

# 修改Docker默认DNS
# /etc/docker/daemon.json
{
  "dns": ["8.8.8.8", "8.8.4.4"]
}

# 重启Docker
systemctl restart docker

端口不通问题:

# 查看端口映射
docker port nginx

# 查看容器端口
docker inspect --format '{{.NetworkSettings.Ports}}' nginx

# 查看主机端口监听
netstat -tulnp | grep :80

# 检查防火墙规则
iptables -L -n

# 开放端口
firewall-cmd --add-port=80/tcp --permanent
firewall-cmd --reload

# 或者关闭防火墙
systemctl stop firewalld

4.2 容器间通信问题

4.2.1 容器间无法通信

排查容器间通信:

# 1. 查看容器网络
docker network inspect bridge

# 2. 查看容器IP
docker inspect --format '{{.NetworkSettings.IPAddress}}' nginx
docker inspect --format '{{.NetworkSettings.IPAddress}}' mysql

# 3. 测试容器间连通性
docker exec nginx ping -c 4 <mysql_ip>

# 4. 测试服务端口
docker exec nginx telnet <mysql_ip> 3306

# 5. 查看容器网络模式
docker inspect --format '{{.HostConfig.NetworkMode}}' nginx
docker inspect --format '{{.HostConfig.NetworkMode}}' mysql

# 6. 查看防火墙规则
iptables -L -n | grep docker

解决方案:

# 1. 确保容器在同一网络
docker network create mynetwork
docker network connect mynetwork nginx
docker network connect mynetwork mysql

# 2. 使用容器名称通信
docker exec nginx ping -c 4 mysql

# 3. 使用--link(已废弃)
docker run -d --name nginx --link mysql:mysql nginx:latest

# 4. 检查防火墙规则
iptables -L -n | grep DROP

# 5. 重启Docker网络
systemctl restart docker

4.2.2 跨主机通信问题

排查跨主机通信:

# 1. 查看overlay网络
docker network ls | grep overlay

# 2. 查看网络详情
docker network inspect myoverlay

# 3. 测试跨主机连通性
docker exec nginx ping -c 4 <remote_container_ip>

# 4. 查看VXLAN配置
ip link show

# 5. 查看端口开放
netstat -tulnp | grep 4789

# 6. 查看防火墙规则
iptables -L -n | grep 4789

解决方案:

# 1. 开放VXLAN端口
firewall-cmd --add-port=4789/udp --permanent
firewall-cmd --reload

# 2. 配置overlay网络
docker network create \
  --driver overlay \
  --subnet=10.0.0.0/24 \
  myoverlay

# 3. 连接容器到overlay网络
docker network connect myoverlay nginx

# 4. 检查etcd/consul配置
# 确保服务发现正常

五、存储故障排查

5.1 数据卷挂载失败

5.1.1 挂载失败原因

常见挂载失败原因:

数据卷挂载失败原因:
┌──────────────────┬──────────────┬──────────────┐
│     原因类型     │   现象       │   解决方法   │
├──────────────────┼──────────────┼──────────────┤
│  路径不存在     │ 路径未找到    │ 创建路径     │
│  权限问题       │ 权限拒绝      │ 调整权限     │
│  磁盘空间不足   │ 空间不足      │ 清理空间     │
│  SELinux限制    │ 访问被拒绝    │ 配置SELinux │
│  挂载点被占用   │ 设备忙        │ 卸载后重试   │
└──────────────────┴──────────────┴──────────────┘

排查步骤:

# 1. 查看容器挂载信息
docker inspect --format '{{.Mounts}}' nginx

# 2. 查看详细挂载信息
docker inspect --format '{{json .Mounts}}' nginx | jq

# 3. 查看容器日志
docker logs nginx

# 错误信息
docker: Error response from daemon: error while creating mount source path '/host/data': mkdir /host/data: permission denied.

# 4. 检查主机路径
ls -ld /host/data

# 5. 检查磁盘空间
df -h /host/data

# 6. 检查SELinux状态
getenforce

# 7. 查看SELinux日志
ausearch -m avc -ts recent

5.1.2 挂载失败解决方案

路径不存在:

# 创建主机路径
mkdir -p /host/data

# 重新启动容器
docker run -d \
  --name nginx \
  -v /host/data:/data \
  nginx:latest

权限问题:

# 修改目录权限
chmod 755 /host/data

# 修改目录所有者
chown -R 1000:1000 /host/data

# 使用--user参数
docker run -d \
  --name nginx \
  --user 1000:1000 \
  -v /host/data:/data \
  nginx:latest

# 使用特权模式(不推荐)
docker run -d \
  --name nginx \
  --privileged \
  -v /host/data:/data \
  nginx:latest

SELinux问题:

# 方法1: 添加SELinux标签
chcon -Rt svirt_sandbox_file_t /host/data

# 方法2: 使用:z或:Z后缀
docker run -d \
  --name nginx \
  -v /host/data:/data:z \
  nginx:latest

# 方法3: 临时禁用SELinux(不推荐)
setenforce 0

# 方法4: 配置SELinux策略
# 创建自定义策略

5.2 磁盘空间不足

5.2.1 磁盘空间排查

查看磁盘使用:

# 查看系统磁盘使用
df -h

# 输出
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1        50G   45G  5.0G  90% /
/dev/sda2       100G   80G   20G  80% /data

# 查看Docker磁盘使用
docker system df

# 输出
TYPE                TOTAL               ACTIVE              SIZE                RECLAIMABLE
Images              15                  10                  5.5GB               2.5GB (45%)
Containers          20                  15                  1.2GB               500MB (41%)
Local Volumes       10                  8                   800MB               300MB (37%)
Build Cache         50                  0                   2.1GB               2.1GB (100%)

# 查看Docker目录大小
du -sh /var/lib/docker/*

# 输出
1.5G    /var/lib/docker/containers
3.2G    /var/lib/docker/images
800M    /var/lib/docker/volumes
2.1G    /var/lib/docker/buildkit

# 查看容器日志大小
du -sh /var/lib/docker/containers/*/*-json.log

5.2.2 磁盘空间清理

清理Docker资源:

# 清理所有无用资源
docker system prune -a

# 输出
WARNING! This will remove:
  - all stopped containers
  - all networks not used by at least one container
  - all images without at least one container associated to them
  - all build cache
Are you sure you want to continue? [y/N] y

# 清理镜像
docker image prune -a

# 清理容器
docker container prune

# 清理卷
docker volume prune

# 清理网络
docker network prune

# 清理构建缓存
docker builder prune -a

# 清理特定镜像
docker rmi $(docker images -f "dangling=true" -q)

# 清理停止的容器
docker rm $(docker ps -a -q)

# 清理未使用的卷
docker volume rm $(docker volume ls -qf dangling=true)

日志清理:

# 查看容器日志大小
find /var/lib/docker/containers/ -name *-json.log | xargs du -sh

# 清空容器日志
truncate -s 0 /var/lib/docker/containers/*/*-json.log

# 配置日志大小限制
# /etc/docker/daemon.json
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}

# 重启Docker
systemctl restart docker

# 重启容器使配置生效
docker restart nginx

六、守护进程故障排查

6.1 Docker服务无法启动

6.1.1 服务启动失败

排查服务问题:

# 1. 查看Docker服务状态
systemctl status docker

# 输出
● docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
   Active: failed (Result: exit-code) since Mon 2024-01-01 00:00:00 CST; 5s ago
     Docs: https://docs.docker.com
  Process: 12345 ExecStart=/usr/bin/dockerd (code=exited, status=1/FAILURE)
 Main PID: 12345 (code=exited, status=1/FAILURE)

# 2. 查看Docker日志
journalctl -u docker

# 3. 查看系统日志
tail -f /var/log/messages

# 4. 手动启动Docker
dockerd

# 5. 检查配置文件
cat /etc/docker/daemon.json

# 6. 验证配置文件格式
python -m json.tool /etc/docker/daemon.json

常见启动失败原因:

Docker启动失败原因:
┌──────────────────┬──────────────┬──────────────┐
│     原因类型     │   现象       │   解决方法   │
├──────────────────┼──────────────┼──────────────┤
│  配置错误       │ 配置文件错误  │ 检查配置     │
│  端口占用       │ 端口被占用    │ 更换端口     │
│  存储驱动错误   │ 驱动不支持    │ 更换驱动     │
│  权限问题       │ 权限不足      │ 调整权限     │
│  依赖缺失       │ 依赖未安装    │ 安装依赖     │
│  内核版本低     │ 内核不支持    │ 升级内核     │
└──────────────────┴──────────────┴──────────────┘

6.1.2 服务启动失败解决方案

配置错误:

# 检查配置文件语法
python -m json.tool /etc/docker/daemon.json

# 错误示例
# /etc/docker/daemon.json
{
  "storage-driver": "overlay2",
  "log-level": "debug",
  "registry-mirrors": [
    "https://mirror.ccs.tencentyun.com"
  ]
}  # 缺少逗号或括号

# 正确示例
{
  "storage-driver": "overlay2",
  "log-level": "debug",
  "registry-mirrors": [
    "https://mirror.ccs.tencentyun.com"
  ]
}

# 备份并删除配置文件
mv /etc/docker/daemon.json /etc/docker/daemon.json.bak

# 重启Docker
systemctl restart docker

端口占用:

# 查看端口占用
netstat -tulnp | grep 2375

# 停止占用端口的进程
kill -9 <pid>

# 修改Docker端口
# /etc/docker/daemon.json
{
  "hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2376"]
}

# 重启Docker
systemctl restart docker

存储驱动错误:

# 查看支持的存储驱动
docker info | grep "Storage Driver"

# 修改存储驱动
# /etc/docker/daemon.json
{
  "storage-driver": "overlay2"
}

# 清理旧数据(谨慎操作)
rm -rf /var/lib/docker/*

# 重启Docker
systemctl restart docker

6.2 Docker命令无响应

6.2.1 命令卡死问题

排查命令无响应:

# 1. 查看Docker进程
ps aux | grep docker

# 2. 查看进程状态
top -p $(pgrep dockerd)

# 3. 查看进程线程
pstree -p $(pgrep dockerd)

# 4. 查看进程栈
cat /proc/$(pgrep dockerd)/stack

# 5. 查看系统调用
strace -p $(pgrep dockerd)

# 6. 查看文件描述符
lsof -p $(pgrep dockerd)

# 7. 查看网络连接
netstat -tulnp | grep docker

解决方案:

# 1. 等待命令完成
# 某些操作可能需要较长时间

# 2. 重启Docker服务
systemctl restart docker

# 3. 查看死锁
cat /proc/$(pgrep dockerd)/stack

# 4. 强制停止Docker
systemctl kill docker

# 5. 清理残留进程
pkill -9 dockerd
pkill -9 docker-proxy

# 6. 清理残留文件
rm -f /var/run/docker.pid
rm -f /var/run/docker.sock

# 7. 重启Docker
systemctl start docker

七、本章小结

7.1 核心概念总结

7.1.1 故障排查要点

容器故障排查:
├─ 启动失败: 检查日志、配置、资源
├─ 运行异常: 检查资源、应用、网络
├─ 无法停止: 检查进程、信号、状态
└─ 性能问题: 检查资源、配置、应用

镜像故障排查:
├─ 拉取失败: 检查网络、认证、空间
├─ 构建失败: 检查Dockerfile、网络、权限
└─ 镜像损坏: 重新拉取或构建

网络故障排查:
├─ 连接问题: 检查网络配置、防火墙
├─ DNS问题: 检查DNS配置
└─ 端口问题: 检查端口映射、占用

存储故障排查:
├─ 挂载失败: 检查路径、权限、SELinux
├─ 空间不足: 清理无用资源
└─ IO问题: 检查存储驱动、配置

守护进程故障排查:
├─ 启动失败: 检查配置、端口、驱动
├─ 命令无响应: 检查进程、资源
└─ 权限问题: 检查用户、组、权限

7.1.2 故障排查工具

Docker工具:
├─ docker ps: 查看容器状态
├─ docker logs: 查看容器日志
├─ docker inspect: 查看容器详情
├─ docker stats: 查看资源使用
└─ docker events: 查看Docker事件

系统工具:
├─ journalctl: 查看系统日志
├─ top/htop: 查看系统资源
├─ netstat/ss: 查看网络连接
├─ lsof: 查看文件描述符
└─ strace: 跟踪系统调用

7.2 最佳实践

7.2.1 故障预防建议

预防措施:
✅ 定期备份重要数据
✅ 监控系统资源使用
✅ 配置日志轮转
✅ 设置资源限制
✅ 使用健康检查
✅ 配置自动重启
✅ 定期清理无用资源
✅ 文档化配置和变更

7.2.2 故障处理建议

处理原则:
✅ 保持冷静,系统化排查
✅ 收集完整信息
✅ 由简到繁排查
✅ 记录排查过程
✅ 验证解决方案
✅ 总结经验教训
✅ 制定预防措施

7.3 下一章预告

下一章: Docker最佳实践

将学习:

  • 🎯 镜像构建最佳实践
  • 🔐 安全最佳实践
  • 📊 监控最佳实践
  • 🚀 部署最佳实践

📝 练习题

基础题

  1. 容器启动失败: 一个容器启动后立即退出,如何排查问题?

  2. 镜像拉取失败: 从Docker Hub拉取镜像失败,如何解决?

  3. 网络不通: 容器无法访问外网,如何排查?

进阶题

  1. 磁盘空间不足: Docker所在磁盘空间不足,如何清理?

  2. 容器频繁重启: 一个容器频繁重启,如何找出原因并解决?

  3. Docker服务无法启动: Docker服务启动失败,如何排查?

实践题

  1. 完整故障排查: 模拟一个Docker应用故障,要求:

    • 容器无法启动
    • 日志分析
    • 问题定位
    • 解决问题
    • 验证修复
  2. 故障排查文档: 编写一份Docker故障排查文档,包含:

    • 常见故障类型
    • 排查步骤
    • 解决方案
    • 预防措施