docker容器重启策略
收到有关Docker容器已停产的通知是度过一整夜的最糟糕方法之一。 在今天的文章中,我们将讨论如何使用Docker的重新启动策略自动重新启动容器并避免那些深夜通知。
应用程序崩溃时会发生什么?
在开始使用Docker的重启策略之前,让我们进一步了解Docker在应用程序崩溃时的行为。 为方便crash.sh
,我们将创建一个Docker容器,该容器执行一个名为crash.sh
的简单bash脚本。
#/bin/bash
sleep 30
exit 1
上面的脚本很简单; 启动时,它将sleep
30
秒钟,然后exit
,退出代码为1
表示错误。
构建和运行自定义容器
为了在容器中运行此脚本,我们需要构建一个自定义Docker容器,其中包含crash.sh
脚本。 为了构建自定义容器,我们首先需要创建一个简单的Dockerfile
。
$ vi Dockerfile
Dockerfile
将包含以下三行:
FROM ubuntu:14.04
ADD crash.sh /
CMD /bin/bash /crash.sh
上面的Dockerfile
将基于最新的ubuntu:14.04
镜像构建一个容器。 还将把crash.sh
脚本添加到容器的/
目录中。 最后一行告诉Docker在容器启动时执行crash.sh
脚本。
定义了Dockerfile
,我们现在可以使用Dockerfile
docker build
命令构建自定义容器。
$ sudo docker build -t testing_restarts ./
Sending build context to Docker daemon 3.072 kB
Step 1 : FROM ubuntu:14.04
---> e36c55082fa6
Step 2 : ADD crash.sh /
---> eb6057d904ef
Removing intermediate container 5199db00ba76
Step 3 : CMD /bin/bash /crash.sh
---> Running in 01e6f5e12c3f
---> 0e2f4ac52f19
Removing intermediate container 01e6f5e12c3f
Successfully built 0e2f4ac52f19
此构建命令创建了一个带有标记名称testing_restarts
的Docker映像。 现在我们可以通过执行docker run
来使用testing_restarts
镜像启动一个容器。
$ sudo docker run -d --name testing_restarts testing_restarts
a35bb16634a029039c8b34dddba41854e9a5b95222d32e3ca5624787c4c8914a
从上面可以看出,Docker能够启动一个名为testing_restarts
的容器。 让我们通过运行docker ps
检查该容器的状态。
$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
docker ps
命令不显示任何正在运行的容器。 原因是因为docker ps
默认情况下仅显示正在运行的容器。 让我们通过使用-a
标志来查看正在运行和未运行的容器。
$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a35bb16634a0 testing_restarts "/bin/sh -c '/bin/bas" 9 minutes ago Exited (1) 8 minutes ago
通过docker ps
结果,我们可以看到,当Docker容器中的应用程序退出时,该容器也将停止。 这意味着默认情况下,如果在容器中运行的应用程序崩溃,则该容器将停止,并且该容器将保持停止状态,直到有人或某物重新启动它为止。
!新的号召性用语
更改Docker的默认行为
通过在启动容器时指定重启策略,可以自动重启崩溃的容器。 为了更好地了解重新启动策略,让我们看看在同一容器中使用always
重新启动策略时会发生什么。
$ sudo docker run -d --name testing_restarts --restart always testing_restarts
8320e96172e4403cf6527df538fb7054accf3a55513deb12bb6a5535177c1f19
在上面的命令中,我们指定Docker应该通过--restart
标志将always
重启策略应用于此容器。 让我们再次执行docker ps
看看这对我们的容器有什么影响。
$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8320e96172e4 testing_restarts "/bin/sh -c '/bin/bas" About a minute ago Up 21 seconds
这次我们可以看到容器已启动并正在运行,但仅持续了21
秒。 如果再次运行docker ps
,我们将看到一些有趣的东西。
$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8320e96172e4 testing_restarts "/bin/sh -c '/bin/bas" About a minute ago Up 19 seconds
第二次运行显示容器仅用了19
秒钟。 这意味着,即使我们的应用程序( crash.sh
)继续因错误退出,但Docker每次退出时都会不断重启容器。
现在我们了解了如何使用重启策略来更改Docker的默认行为,让我们看一下Docker提供了哪些重启策略。
Docker的重启策略
Docker当前有四个重启策略:
-
no
-
on-failure
-
unless-stopped
-
always
no
策略是默认的重启策略,在任何情况下都不会重启容器。
失败时重新启动,但成功时停止
on-failure
策略有点有趣,因为它允许您告诉Docker如果退出代码指示错误,则重新启动容器,但是如果退出代码指示成功,则不通知。 您还可以指定Docker自动重新启动容器的最大次数。
让我们使用testing_restarts
容器尝试这种重启策略,并设置5
重启的限制。
$ sudo docker run -d --name testing_restarts --restart on-failure:5 testing_restarts
85ff2f096bac9965a9b8cffbb73c1642bf7b64a2173bbd145961231861b95819
如果我们在启动容器后的一分钟内运行docker ps
,我们将看到该容器正在运行并且最近已启动。
$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
85ff2f096bac testing_restarts "/bin/sh -c '/bin/bas" About a minute ago Up 8 seconds
但是,如果我们在启动容器后3
分钟运行docker ps
命令,情况就不会如此。
$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
85ff2f096bac testing_restarts "/bin/sh -c '/bin/bas" 3 minutes ago Exited (1) 20 seconds ago
从上面我们可以看到,在3
分钟后容器被停止了。 这是由于以下事实:重新启动容器max-retries
超过了我们的max-retries
设置。
有了成功
on-failures
的好处是,当应用程序以成功的退出代码退出时,将不会重新启动容器。 让我们通过对crash.sh
脚本进行快速的微小更改来了解这crash.sh
。
$ vi crash.sh
更改将退出代码设置为0
。
#/bin/bash
sleep 30
exit 0
通过将脚本设置为以0
退出代码退出,我们将从脚本中删除错误指示符。 据Docker所知,该脚本每次都会成功执行。
更改脚本后,我们将需要重新构建容器,然后才能再次运行它。
$ sudo docker build -t testing_restarts ./
Sending build context to Docker daemon 3.072 kB
Step 1 : FROM ubuntu:14.04
---> e36c55082fa6
Step 2 : ADD crash.sh /
---> a4e7e4ad968f
Removing intermediate container 88115fe05456
Step 3 : CMD /bin/bash /crash.sh
---> Running in fc8bbaffd9b9
---> 8aaa3d99f432
Removing intermediate container fc8bbaffd9b9
Successfully built 8aaa3d99f432
重建容器映像后,让我们以相同的on-failures
和max-retries
设置再次启动该容器。
$ sudo docker run -d --name testing_restarts --restart on-failure:5 testing_restarts
f0052e0c509dfc1c1b112c3b3717c23bc66db980f222144ca1c9a6b51cabdc19
这次,当我们执行docker ps -a
执行时,我们应该看到一些不同的结果。
$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f0052e0c509d testing_restarts "/bin/sh -c '/bin/bas" 41 seconds ago Exited (0) 11 seconds ago
由于crash.sh
脚本以成功的退出代码( 0
)退出,因此Docker将其视为成功,因此没有重新启动容器。
始终重新启动容器
如果我们希望无论退出代码如何都重新启动容器,则可以使用一些重新启动策略:
-
always
-
unless-stopped
always
重启策略告诉Docker在每种情况下都要重启容器。 我们较早地尝试了always
重启策略,但是让我们看看使用always
重启策略重新启动当前容器时会发生什么。
$ sudo docker run -d --name testing_restarts --restart always testing_restarts
676f12c9cd4cac7d3dd84d8b70734119ef956b3e5100b2449197c2352f3c4a55
如果我们等待几分钟并再次运行docker ps -a
,则即使退出代码显示成功,我们也应该看到容器已重新启动。
$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9afad0ccd068 testing_restarts "/bin/sh -c '/bin/bas" 4 minutes ago Up 22 seconds
always
重启策略的最大好处是,即使我们的Docker主机在启动时崩溃,Docker服务也会重启我们的容器。 让我们看一下实际操作以充分理解为什么这样做很有用。
$ sudo reboot
默认情况下,甚至是on-failures
,我们的容器在重新启动时都不会运行。 根据容器执行的任务,这可能会有问题。
$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
676f12c9cd4c testing_restarts "/bin/sh -c '/bin/bas" 9 minutes ago Up 2 seconds
对于always
重启策略,情况并非如此。 always
重新启动策略将始终重新启动容器。 即使容器在重新启动之前已停止也是如此。 让我们看看实际情况。
$ sudo docker stop testing_restarts
testing_restarts
$ sudo reboot
在重新启动系统之前,我们只是停止了容器。 这意味着容器仍在那儿,只是没有在运行。 但是,在我们重新启动后备份系统后,该容器将运行。
$ sudo docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
676f12c9cd4c testing_restarts "/bin/sh -c '/bin/bas" 11 minutes ago Up 24 seconds
重新启动后我们的容器运行的原因是由于always
策略。 每当重新启动Docker服务时,无论使用的容器是正在运行还是现在,使用Always策略的容器always
将重新启动。
问题在于,重新启动在重新启动后先前已停止的容器可能会有些问题。 如果我们的容器由于正当的原因而停止运行,或更糟糕的是,如果容器已过时该怎么办?
解决方案是unless-stopped
重启策略。
仅在Docker停止时停止
unless-stopped
重启策略的行为与always
一样,只是一个例外。 当容器停止并且服务器重新启动或Docker服务重新启动时,该容器将不会重新启动。
让我们通过使用“ unless-stopped
策略启动容器并重复我们的上一个示例,来实际了解这一点。
$ sudo docker run -d --name testing_restarts --restart unless-stopped testing_restarts
fec5be52b9559b4f6421b10fe41c9c1dc3a16ff838c25d74238c5892f2b0b36
在容器运行时,让我们停止它,然后再次重新引导系统。
$ sudo docker stop testing_restarts
testing_restarts
$ sudo reboot
这次系统重新启动时,我们应该看到容器处于停止状态。
$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fec5be52b955 testing_restarts "/bin/sh -c '/bin/bas" 2 minutes ago Exited (137) About a minute ago
unless-stopped
,一项重要的事项是,如果容器在重新引导之前正在运行,则一旦系统重新启动,容器就会被重新引导。 我们可以通过重新启动容器并再次重新启动系统来查看运行中的情况。
$ sudo docker start testing_restarts
testing_restarts
$ sudo reboot
重新启动后,该容器应该正在运行。
$ sudo docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fec5be52b955 testing_restarts "/bin/sh -c '/bin/bas" 5 minutes ago Up 13 seconds testing_restarts
always
和unless-stopped
之间的差异可能很小,但是在某些环境中,这种微小差异可能是关键的决定。
选择最佳重启策略
选择最佳的重新启动策略时,请务必记住容器正在执行哪种类型的工作负载。
例如,Redis实例可能是您环境中的关键组件,应该具有always
或unless-stopped
策略。 另一方面,批处理应用程序可能需要重新启动,直到过程成功完成。 在这种情况下,使用on-failures
策略是有意义的。
无论哪种方式,使用Docker的重启策略,您现在都可以放心,下次Docker主机在凌晨3点神秘重启时,您的容器将被重启。
参考: | 确保我们的JCG合作伙伴 Ben Cane在Docker的重启策略中始终使容器运行,请访问Codeship Blog博客。 |
翻译自: https://www.javacodegeeks.com/2016/06/ensuring-containers-always-running-dockers-restart-policy.html
docker容器重启策略