Docker 容器重启循环排查:一次博客宕机的完整复盘
网站突然打不开,ssh 上去一看,容器状态显示 Restarting (1),一直在重启循环。这篇文章复盘一次真实的容器故障排查过程,从现象到根因,给出通用的排查套路。
现象
- 博客域名访问返回 502
docker ps显示后端容器Restarting (1),重启计数器一直在涨- 数据库容器和 Redis 容器显示
Exited (0),已经退出了 20 小时
排查第一步:看日志
容器重启循环,第一件事永远是看日志,找到重启的原因:
docker logs <容器名> --tail 30
这次日志明确给出了答案:
应用初始化失败: 创建数据库连接池失败: 无法 Ping 通数据库
(DSN: host=anheyu_postgresql port=5432 user=anheyu ...):
dial tcp: lookup anheyu_postgresql on 127.0.0.11:53: no such host
关键信息是 no such host:应用容器解析不到数据库容器的主机名。这不是网络抖动,而是数据库容器根本没在运行——Exited (0) 状态说明它正常退出了,而且没有 restart 策略,退出后没人拉它起来。
排查第二步:理清依赖关系
这个故障链条非常典型:
- 某次重启(或手动停止)后,数据库容器退出
- 数据库容器没有
restart: always,退出后不会自动恢复 - 应用容器有
restart: always,反复启动 - 每次启动都连不上数据库,初始化失败,再次重启,死循环
docker logs --tail 50—— 看重启原因(90% 的情况日志直接给答案)docker ps -a—— 看所有容器的状态,特别注意Exited的依赖容器ss -tlnp—— 确认服务端口是否在监听- 检查 restart 策略是否覆盖所有服务
- compose 里所有服务统一配
restart: always,别只配主服务 - 数据库、Redis 这类被依赖的容器,挂了影响面最大,更要保证自愈
- 修复后别忘了验证整条链路(应用日志 + 端口 + 公网访问),而不只是容器变 Up
解决:先恢复,再加固
# 1. 先拉起数据库和 Redis(应用会自动连上)
docker start anheyu_postgresql anheyu_redis
# 2. 验证应用恢复
docker ps | grep anheyu # 应该变成 Up 状态
ss -tlnp | grep 8091 # 服务端口恢复监听
恢复后日志显示正常:搜索索引重建完成、前端就绪、接口返回 200。
根因修复:restart 策略要补全
问题根源是数据库容器没配 restart 策略。一个 compose 文件里,如果应用服务配了 restart: always,它的依赖服务也必须配,否则依赖挂了就是上面的死循环:
docker update --restart always anheyu_postgresql anheyu_redis
或者在 docker-compose.yml 里给每个服务都加上:
services:
app:
restart: always
db:
restart: always # 必须也配!
通用排查套路
遇到任何容器重启循环,按这个顺序查:
教训
这次故障从发现到恢复用了十分钟,但真正值钱的是后面的加固:补上 restart 策略后,同类问题基本不会再现了。
本文是原创文章,采用 CC BY-NC-SA 4.0 协议,完整转载请注明来自 江江
评论
隐私政策
0/500
滚动到此处加载评论...
