确保容器始终按照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设置。

有了成功

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-failuresmax-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-stoppedunless-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

alwaysunless-stopped之间的差异可能很小,但是在某些环境中,这种微小差异可能是关键的决定。

选择最佳重启策略

选择最佳重启策略时,请务必记住容器正在执行哪种类型的工作负载。

例如,Redis实例可能是您环境中的关键组件,应该具有alwaysunless-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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值