681 字
3 分钟
Docker 数据持久化与常见故障排查
容器可写层不适合保存重要数据。容器被删除或重建时,业务数据应仍然存在于卷、绑定挂载或外部存储中。
卷与绑定挂载
命名卷:
docker volume create app-datadocker run --rm -v app-data:/data alpine sh -c 'date > /data/created-at'docker run --rm -v app-data:/data alpine cat /data/created-at绑定挂载:
docker run --rm -v "$PWD/config:/app/config:ro" alpine ls -la /app/config- 命名卷由 Docker 管理,适合数据库和应用持久化数据。
- 绑定挂载直接映射宿主机路径,适合配置、源码和明确需要宿主机管理的文件。
- 配置文件尽量使用只读挂载
:ro。
备份命名卷
docker run --rm \ -v app-data:/source:ro \ -v "$PWD/backups:/backup" \ alpine tar -czf /backup/app-data.tar.gz -C /source .恢复前先停止写入该卷的服务,并验证备份文件可读取。
容器反复退出
docker ps -adocker logs --tail 200 container-namedocker inspect container-name --format '{{.State.Status}} {{.State.ExitCode}} {{.State.Error}}'常见退出码:
0:主进程正常结束,可能是启动命令本来就不是长期进程。1:应用通用错误,应查看日志。126:命令存在但不可执行,常见于权限问题。127:命令不存在或 PATH 不正确。137:常见于被SIGKILL终止,包括内存不足。
检查 OOM:
docker inspect container-name --format '{{.State.OOMKilled}}'dmesg -T | grep -i -E 'out of memory|killed process'端口无法访问
docker port container-namedocker inspect container-name --format '{{json .NetworkSettings.Ports}}'ss -lntpcurl -v http://127.0.0.1:8080确认四件事:
- 应用在容器内实际监听目标端口;
- 应用监听
0.0.0.0,而不是只监听容器内127.0.0.1; -p或 Compose 的端口映射正确;- 宿主机防火墙和云安全组允许访问。
容器之间无法连接
docker network lsdocker network inspect network-namedocker exec app getent hosts dbdocker exec app sh -c 'nc -vz db 5432'同一 Compose 项目的服务通常通过服务名互相解析。不要把其他容器地址写成 localhost。
权限问题
宿主机目录的 UID/GID 与容器内用户可能不同:
docker exec container-name idls -ln mounted-directory优先让容器以明确 UID/GID 运行,并设置宿主机目录所有者。避免用 chmod 777 解决数据库目录或密钥文件权限。
空间占用
docker system df -vdocker container ls -adocker image lsdocker volume ls清理前逐项确认:
docker container prunedocker image prunedocker builder prune不要在不清楚卷用途时执行 docker volume prune。
标准排障流程
docker ps -a确认状态和退出时间。docker logs查看应用错误。docker inspect检查命令、环境、挂载、网络和退出码。docker exec在容器内验证进程、DNS、端口和文件权限。- 检查宿主机内存、磁盘、防火墙和内核日志。
- 修复 Dockerfile 或 Compose 配置,不依赖手工修改运行中的容器。
参考资料
Docker 数据持久化与常见故障排查
https://zh19990906.github.io/fuwari/posts/docker-storage-and-troubleshooting/