大家好,我是站长。今天咱们不聊虚的,直接来啃一块运维工作中既基础又容易埋雷的硬骨头——Docker 容器的自启动配置。
很多朋友在测试环境玩 Docker 玩得很溜,docker run -d 一把梭,服务跑得欢快。可一旦上了生产环境,或者仅仅是给家里的 NAS 重启了一下,就发现服务全挂了。登录后台一看,容器全是 Exited 状态。这时候才想起来去查“怎么让 Docker 容器开机自启”,其实已经有点晚了。
今天这篇文章,站长就从底层原理到生产环境的加固 SOP,帮你彻底理清 --restart 策略的每一个细节,让你的容器在宿主机重启时也能“满血复活”。
一、 核心原理:Docker 守护进程与容器生命周期的解耦
💡 推荐阅读:Nginx 防盗链配了还是被刷爆?聊聊我怎么堵住高频 IP 和恶意爬虫的
很多新手会有一个误区:认为 docker run 启动的容器会随着系统启动而自动启动。大错特错!
Docker 采用的是 C/S 架构。宿主机开机时,首先启动的是 dockerd 守护进程。而容器本质上是宿主机上的一个特殊进程,它是否启动,完全取决于 dockerd 在启动时是否收到了“拉起某个容器”的指令。
这个指令的来源,就是我们在创建容器时指定的 Restart Policy(重启策略)。如果没有显式配置这个策略,默认就是 no,意味着哪怕 Docker 服务起来了,它也会假装没看见你的容器。
二、 –restart 策略详解:四种模式的生产环境选型
💡 延伸阅读:Linux 磁盘 100% 别急着删库!老站长手把手教你揪出“空间刺客”并优雅善后
Docker 提供了四种重启策略,站长结合实际踩坑经验,给你逐一拆解:
| 策略名称 | 触发条件 | 生产环境适用场景 |
|---|---|---|
no |
默认值,任何时候都不重启 | 临时调试、一次性任务脚本 |
on-failure[:max-retries] |
仅当容器非零退出码退出时重启 | 批处理任务、需要人工介入排查的异常服务 |
always |
无论退出码是什么,总是重启 | 核心常驻服务(Nginx、MySQL、Redis) |
unless-stopped |
总是重启,除非容器被手动 docker stop |
站长强烈推荐:绝大多数生产环境常驻服务 |
1. 为什么站长首推 unless-stopped?
这里有个非常经典的运维场景:假设你正在维护服务器,手动执行了 docker stop my-app 停掉了服务,然后去吃饭了。此时机房突然断电,来电后服务器自动重启。
- 如果策略是
always:Docker 守护进程启动后,会强制把my-app拉起来。但你可能还没完成维护,这会导致意料之外的服务启动。 - 如果策略是
unless-stopped:Docker 会记住这个容器在被关闭前是“手动停止”的状态,因此即使宿主机重启,它也会保持停止状态,尊重运维人员的操作意图。
2. on-failure 的隐藏陷阱
看起来 on-failure 很智能,只在该重启的时候重启。但站长要提醒你:它无法处理 Docker 守护进程本身重启的情况。如果 dockerd 因为升级或崩溃重启,on-failure 策略的容器是不会被拉起的,因为它并没有“失败退出”,只是随着守护进程一起消失了。对于核心业务,这绝对是致命伤。
三、 生产环境架构规范:如何正确配置与修改
💡 深度技术指南:CPU 飙到 100% 别急着重启!一文讲透云服务器高负载的排查与根治
知道了选什么,还得知道怎么用。下面进入实操环节。
场景一:新建容器时指定策略
在 docker run 命令中直接加入参数,这是最干净的做法:
docker run -d \
--name my-production-db \
--restart unless-stopped \
-v /data/mysql:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=YourStrongPassword \
mysql:8.0
站长提醒:生产环境的数据库,数据卷映射(-v)和重启策略同等重要,千万别把数据留在容器内部。
场景二:修改已运行容器的策略
如果你已经跑了一堆容器,发现没配自启动,难道要删了重建?不需要。docker update 命令可以热更新重启策略:
docker update --restart unless-stopped my-existing-container
这个命令会立即生效,并且不需要重启容器。你可以批量操作:
docker update --restart unless-stopped $(docker ps -aq)
⚠️ 注意:这条批量命令会把所有容器都设为自启,包括那些你只想临时跑跑的测试容器。执行前务必用 docker ps -a 确认清单。
四、 性能与安全加固调优清单
光配好 --restart 就高枕无忧了吗?作为架构师视角,你还得考虑以下加固点:
- 依赖顺序管理:Docker 的自启动是并发的,不保证顺序。如果你的应用容器依赖数据库,即使配了
unless-stopped,也可能因为数据库还没就绪而启动失败。解决方案是使用depends_on配合健康检查(healthcheck),或者更稳妥的 wait-for-it.sh 脚本。 - 资源限制:自启动时若多个重型容器同时拉起,可能导致宿主机 CPU/IO 瞬间打满,引发雪崩。建议在
docker run时加上--cpus和--memory限制。 - 日志轮转:容器自启动后如果疯狂报错,日志会迅速撑爆磁盘。务必配置
--log-opt max-size=100m --log-opt max-file=3。 - Systemd 与 Docker 的博弈:有些朋友喜欢用 Systemd 管理 Docker 容器。站长的建议是:二选一,别混用。既然用了 Docker 原生的
--restart,就不要再写 Systemd unit 文件去docker start,否则容易出现状态不一致的诡异问题。
五、 验证测试与 SOP 总结
配置完成后,必须进行验证。不要直接重启生产服务器!站长推荐的安全验证流程如下:
- 模拟 Docker 守护进程重启:
systemctl restart docker观察容器是否自动拉起:
docker ps。如果看到容器状态是Up,说明策略生效。 - 模拟容器意外崩溃:
docker exec -it my-container kill 1杀掉主进程,观察 Docker 是否在几秒内自动重启该容器。
- 模拟手动停止后重启宿主机(针对 unless-stopped):
docker stop my-container systemctl restart docker此时容器应该保持
Exited状态,证明策略符合预期。
SOP 总结清单:
- ✅ 核心常驻服务统一使用
--restart unless-stopped。 - ✅ 使用
docker update批量修正存量容器。 - ✅ 必须配置日志轮转,防止磁盘写满。
- ✅ 应用启动脚本需包含依赖服务的就绪等待逻辑。
- ✅ 定期通过
systemctl restart docker验证自启动有效性。
最后多说一句,Docker 的自启动虽然方便,但它只是高可用架构中的一环。如果你的业务真的到了分秒必争的地步,建议还是上 Kubernetes 或者 Docker Swarm 来做集群编排。当然,对于大多数中小型项目和个人站长来说,把 --restart 策略吃透,已经能解决 90% 的“服务失联”问题了。
好了,今天的分享就到这里。如果你在配置过程中遇到什么奇葩问题,欢迎在评论区留言,站长看到会第一时间回复。别忘了,服务器稳定性无小事,赶紧去检查一下你的容器重启策略吧!