1. 问题现象与初步排查
遇到Docker服务运行正常但镜像和容器列表显示为空的情况,确实会让开发者感到困惑。我最近在CentOS 7.9系统上就碰到了这个典型问题——系统重启后,执行docker ps -a和docker images命令都返回空结果,而systemctl status docker却显示服务正在正常运行。
首先需要确认几个关键点:
- Docker服务确实在运行(
sudo systemctl is-active docker返回active) - 当前用户有执行docker命令的权限(属于docker用户组)
- 没有使用
--all等过滤参数导致结果为空
通过journalctl -u docker --no-pager -n 50查看日志,我发现关键线索:
code复制level=warning msg="Unable to find runtime root /var/lib/docker/containerd"
level=error msg="failed to start containerd: mkdir /var/lib/docker/containerd: permission denied"
2. 根因分析与解决方案
2.1 存储驱动与目录权限问题
Docker默认使用/var/lib/docker作为存储目录,其中包含镜像、容器等所有数据。系统重启后出现空列表,最常见的原因是:
-
存储驱动变更:检查
/etc/docker/daemon.json是否被修改过。不同存储驱动(overlay2、devicemapper等)对应的数据存储方式不同,驱动不匹配会导致无法识别已有数据。 -
目录权限异常:特别是使用SELinux的系统,重启后安全上下文可能重置。执行:
bash复制sudo chown -R root:docker /var/lib/docker
sudo chmod -R 775 /var/lib/docker
sudo restorecon -Rv /var/lib/docker
- 挂载点丢失:如果/var/lib/docker是独立分区,检查/etc/fstab配置确保正确挂载。
2.2 文件系统损坏修复
当存储目录损坏时,可以尝试恢复:
bash复制sudo systemctl stop docker
sudo rm -rf /var/lib/docker/containerd
sudo systemctl start docker
对于btrfs文件系统,可能需要特殊处理:
bash复制sudo btrfs filesystem defragment -r /var/lib/docker
sudo btrfs filesystem balance /var/lib/docker
3. 深度排查与数据恢复
3.1 检查底层存储状态
使用docker info查看存储驱动和根目录信息:
bash复制Storage Driver: overlay2
Backing Filesystem: xfs
Supports d_type: true
Native Overlay Diff: true
关键验证点:
- Backing Filesystem是否匹配实际文件系统
- Supports d_type是否为true(ext4需要启用此特性)
3.2 手动恢复镜像和容器
如果基础服务正常但仍看不到原有资源,可以尝试:
- 查找残留的镜像层:
bash复制sudo find /var/lib/docker -name "layerdb" -type d
- 恢复容器元数据:
bash复制sudo ls -l /var/lib/docker/containers
- 重建存储数据库:
bash复制sudo docker system prune -a --volumes
sudo systemctl restart docker
4. 预防措施与最佳实践
4.1 配置持久化存储
在/etc/docker/daemon.json中添加稳定配置:
json复制{
"data-root": "/mnt/docker-data",
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.override_kernel_check=true"
]
}
4.2 定期备份关键数据
创建备份脚本:
bash复制#!/bin/bash
BACKUP_DIR=/backup/docker-$(date +%Y%m%d)
mkdir -p $BACKUP_DIR
sudo rsync -a /var/lib/docker/ $BACKUP_DIR/
sudo tar -czvf $BACKUP_DIR.tar.gz $BACKUP_DIR
4.3 系统级防护配置
- 确保docker.service有正确的重启策略:
ini复制[Service]
Restart=always
StartLimitIntervalSec=0
- 配置cron定期检查:
bash复制0 * * * * /usr/bin/docker info > /dev/null || systemctl restart docker
5. 疑难问题排查指南
5.1 常见错误代码处理
| 错误码 | 原因 | 解决方案 |
|---|---|---|
| ERRO[0000] | 存储驱动加载失败 | 检查内核模块是否加载(lsmod | grep overlay) |
| permission denied | 目录权限问题 | 执行chcon -R -t container_file_t /var/lib/docker |
| no space left | 存储空间不足 | 使用docker system prune清理或调整存储限制 |
5.2 高级诊断命令
- 检查存储驱动状态:
bash复制sudo dockerd --debug --storage-driver=overlay2
- 分析镜像层关系:
bash复制docker history <image_id>
- 检查容器日志:
bash复制sudo cat /var/lib/docker/containers/<container_id>/<container_id>-json.log
6. 典型场景解决方案
对于CentOS/RHEL系统特别需要注意:
- 关闭firewalld或正确配置规则
- 确保selinux处于permissive模式
- 更新到最新docker-ce版本
Ubuntu/Debian系统常见问题:
- apparmor配置冲突
- /var/lib/docker使用aufs时的兼容性问题
- 需要手动安装cgroupfs-mount
在Windows系统上:
- 检查Hyper-V是否启用
- 确认WSL2正确安装
- 重置Docker Desktop数据可能需要使用
wsl --unregister docker-desktop-data
7. 恢复后的验证步骤
- 基础功能测试:
bash复制docker run --rm hello-world
- 数据完整性检查:
bash复制docker exec <container> sh -c "find / -type f -exec md5sum {} +" > checksums.txt
- 性能基准测试:
bash复制docker run --rm -it alpine sh -c "time dd if=/dev/zero of=test.img bs=1G count=1"
8. 后续维护建议
- 监控docker存储使用情况:
bash复制watch -n 60 'df -h /var/lib/docker; du -sh /var/lib/docker/*'
- 设置自动清理策略:
bash复制docker system prune -af --filter "until=24h"
- 日志轮转配置(/etc/docker/daemon.json):
json复制{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
这个问题本质上反映了Docker存储子系统与宿主机的交互复杂性。经过多次实践,我总结出一个黄金法则:任何涉及存储配置的变更,都应该先做好完整备份,然后分阶段验证。特别是在生产环境,建议先在测试机模拟重启场景验证配置的可靠性。
