公司内部的服务突然挂了,运维小李接到报警时正在吃午饭。他放下筷子,登录服务器一看,Docker 容器已经停止运行,接口全部超时。这种场景在日常开发中太常见了,靠手动重启治标不治本,得有一套靠谱的恢复方案才行。
为什么需要容器恢复机制
容器虽然轻量灵活,但也不是永不宕机。应用崩溃、资源不足、依赖中断都可能导致容器退出。没有自动恢复机制的话,每次出问题都得人工介入,半夜被叫起来修服务谁也扛不住。
Docker 自带重启策略
Docker 提供了 --restart 参数,能根据容器退出状态决定是否重启。最常用的有三种模式:
- no:不自动重启(默认)
- on-failure:非正常退出时重启
- always:无论为何退出都重启
比如启动一个带自动恢复的 Nginx 容器:
docker run -d --name web-server --restart always -p 80:80 nginx
这样即使服务器重启或者容器意外终止,Docker 也会把它拉起来。
更复杂的恢复用 Docker Compose
微服务项目通常不止一个容器,这时候用 Docker Compose 管理更方便。在 docker-compose.yml 里加上 restart 配置:
version: '3'
services:
app:
image: my-web-app
restart: on-failure:3
ports:
- "3000:3000"
db:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD: example
restart: always
这里 app 服务只在失败时最多重启三次,而数据库则无论如何都要保持运行。
Kubernetes 的健康检查和自愈
在生产环境,很多人用 Kubernetes(K8s)管理容器集群。它不仅能自动重启 Pod,还能通过健康探针判断应用是否真正常。
比如给 Pod 加个 liveness 探针:
apiVersion: v1
kind: Pod
metadata:
name: health-app
spec:
containers:
- name: app
image: my-app
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
如果 /health 接口连续失败,K8s 就会自动重启这个容器。还有 readinessProbe 可以控制流量何时进入,避免刚启动就打满请求。
别忘了数据持久化
光重启容器还不够。如果容器里的日志或配置丢了,重启也没用。关键数据一定要挂载到外部卷:
docker run -d \
--name db-container \
--restart always \
-v /host/data:/var/lib/mysql \
mysql:5.7
这样即使容器重建,数据依然保留,恢复才真正有意义。
监控和告警配合使用
自动恢复是基础,但你还得知道什么时候发生了恢复。结合 Prometheus 和 Grafana 监控容器重启次数,设置告警规则。比如一分钟内重启超过两次,立刻通知负责人,可能是代码本身有问题,不能靠重启硬撑。
小李后来把所有核心服务都加上了 restart: always 和健康检查,再也没被半夜电话吵醒过。容器出问题不可怕,关键是有一套安静又可靠的恢复机制在背后兜底。