Docker 重启策略详解
前言
使用 docker 有挺长的时间了,容器启动时常用的参数来来回回还是那几个。是时候对那些似懂非懂的配置项做个深度解析了,现在就将 docker 容器的重启策略详细讲解一下。
docker 容器的重启策略有下面四种:
- no
- always
- on-failure
- unless-stopped
no— 是默认的重启策略,docker 容器如启动失败或意外停止后 Docker Daemon 不会尝试进行重启,除非手动启动容器,否则一直是 stop 的状态。
always— 表示永远重启。如果你使用docker stop命令停止了容器则 docker 不会自行启动该容器,但如果执行docker stop命令后重启了 Docker Daemon 则该容器会触发always重启策略,进而启动容器。
on-failure— 重启策略的触发标准是当 Docker Daemon 检测到容器非正常停止后则会执行该重启策略。on-failure要求传入一个整型参数表示重启次数,当重启次数>=该整数值则不会予以重启。
unless-stopped— 重启策略与always很相似,唯一不同处在于unless-stopped会在 Docker Daemon 启动时检测容器列表内容器在上次停止时的状态,如果上一次容器停止时就是 stop 状态则不会启动该容器,否则启动该容器。
实践 (放码过来)
纸上得来终觉浅,绝知此事要躬行。我们用一个小的 demo 来模拟上面的四种重启策略,进而加深对它们的认知。使用一个 shell 脚本,脚本本身不会做任何事情,它存活 20 秒后则会非正常停止(容器状态会变更为 stop),我们在装有 docker 的 linux 服务器上创建如下脚本。
#/bin/bash
sleep 20
exit 1创建 Dockerfile,将 shell 脚本 add 到容器内并使用 bash 执行此脚本。Dockerfile 内容如下:
FROM ubuntu
ADD test.sh /
CMD /bin/bash /test.sh执行命令 docker build -t test-restart . 构建 docker 镜像。
现在准备工作均已完成,我们开始测试 docker 容器的重启策略。
no 重启策略实践
docker run -d --name=test-restart-no test-restart容器创建完毕后通过 docker ps 观察已启动的容器列表会发现 test-restart-no 容器坚持了 20 秒后就停止了,且 docker daemon 并未重启该容器。说明 no 策略很诚实,对得起它的命名。
结论:no 重启策略不管容器启动执行结果,失败也好成功也罢但凡容器状态变更为 stop 也不会予以任何动作。
always 策略
docker run -d --restart=always --name=test-restart-always test-restart通过 docker ps | grep restart 监控 test-restart-always 容器发现当 20 秒到达后 docker daemon 会将此容器重新启动,因为可以无限重启,所以虽然每次容器的生命周期都只有 20 秒,但都可以重启,所以表面上看像是一直在启动。我们手动执行 docker stop test-restart-always 停止容器,然后再执行 systemctl restart docker 重启 docker daemon。这时候发现之前手动停止的 test-restart-always 容器已经被自动启动了。
结论:always 重启策略会在容器非正常停止的基础上重新启动容器,如若我们手动停止了容器则不会重启,但是当 docker daemon 重启后也会将设定了 always 策略的容器启动起来。
on-failure 策略
docker run -d --restart=on-failure:3 --name=test-restart-on-failure test-restart通过 docker ps 观察执行结果,我们发现 test-restart-on-failure 容器在运行 20 秒后就会意外关闭,然后会触发 on-failure 策略再次重启,当重启 3 次后容器再一次停止,这一次 docker daemon 没有再重启该容器了。
结论:on-failure 的数值参数并不会在容器重启成功后重新计算,只要执行了重启,不论重启操作的结果如何 docker daemon 都会累加该重启次数与传入的参数值做比较。
unless-stopped 策略
docker run -d --restart=unless-stopped --name=test-restart-unless-stopped test-restart上面的命令执行后的结果和 always 策略一样,完全没有不同的感受,但我们执行 docker stop test-restart-unless-stopped 停止了该容器,再重启 docker daemon 后发现容器 test-restart-unless-stopped 并没有重启,而容器 test-restart-always 却再次重启了。
结论:docker daemon 会在每次启动后检查容器列表中重启策略为 unless-stopped 的容器,如若这些容器在 docker daemon 上次停止时最后状态是 stop 则不启动该容器,否则启动该容器。这也是它与 always 策略的根本区别!