如何以"always"模式重新启动现有的Docker容器?

55

当你从一个镜像中最初运行Docker容器时,你可以指定选项:

--restart="always"

这样可以确保如果容器因某种原因停止,Docker守护程序将始终重新启动容器。因此,您可以像这样运行一个容器:

docker run --restart="always" <IMAGE>

您也可以通过指定容器ID来重新启动现有的Docker容器,例如:

docker start <CONTAINER ID>

然而,我无法确定是否可以更改现有容器的设置,原先未使用 --restart="always" 选项运行。将其转换为在未来始终自动重启。

目前,我所能想到的唯一方法是将该容器保存为新镜像,然后使用 --restart="always" 选项运行该镜像作为新容器。这样做是否正确?

编辑:我最初可能没有表述清楚的是,我考虑的情况是容器自原始运行以来发生了更改,这些更改需要持久保存。因此,仅从原始镜像运行新容器是不够的。


1
更多或更少的副本: https://dev59.com/718d5IYBdhLWcg3waxkp - Tomasz Gandor
4个回答

110

现在我们拥有Docker的update功能,它允许修改正在运行的容器的重启策略。

docker update --restart=always <CONTAINER ID>

另外还有三个选项:

  • 不使用(默认)
  • 在失败时重启
  • 除非手动停止

详细信息请参考链接


1
这是在哪个版本的Docker中引入的? - Richard Corfield
3
自1.11.0版本起已经可以使用。 - Frank Wong
为什么我们在Kitematic中看不到这个?有人知道吗? - Piotr Kula

15

好的,回答我的问题,似乎不可能只使用--restart=always重启同一个容器,因为这是你第一次运行一个容器时必须做的事情,而不是你在启动现有容器时可以使用的参数。

有三种可能的解决方法:

  1. 正如@user2915097所述,您可以放弃原始容器(停止它,然后使用docker rm <CONTAINER ID>删除它以进行整理)。然后,仅从原始映像中运行一个新的容器,这次指定-restart=always选项。
  2. 如果没有使用卷,因此更改仅限于容器内部,则需要将容器提交到新映像,然后从该映像运行新容器。

    docker commit <CONTAINER ID> <NEW IMAGE NAME>

    docker run -d --restart=always ... <NEW IMAGE NAME>

  3. 如果使用了卷并且所有更改都限制在卷中,则可以使用--volumes-from参数运行第二个容器,而无需提交映像的新版本。即:

    • docker stop <CONTAINER 1 NAME>
    • docker run -d --restart=always --volumes-from <CONTAINER 1 NAME> ... <ORIGINAL IMAGE NAME>

    然后可以安全地删除容器1,因为当另一个容器继续使用它们时,卷不会被删除。

我想还有第四种可能性; 如果您使用了一个或多个卷,并且知道容器上存在没有在卷中的更改,则必须使用(2)和(3)的组合。


3

更新:这个方法可以使重启生效。但将其设置回“no”,它会被重置为“always”,容器会重新启动! :( 我会把这个答案留在这里,以防有人弄清楚了这是如何工作的。我一定很接近了!

朋友们,我找到了最hacky的解决方案,可以避免复制容器等问题。

vi /var/lib/docker/containers/$(docker inspect -f '{{ .Id }}' $ContainerID)/hostconfig.json

搜索“RestartPolicy”。将其设置为“no”、“always”等。

也许有人可以将其包装成一个脚本!?

无论如何,那个json片段以及config.json文件将允许您修改创建容器时错过的各种东西。


警告任何尝试此操作的人,Docker的许多状态管理都是基于它是唯一修改/var/lib/docker内容的假设。在此处进行更改时要非常小心。 - Kevan Ahlquist
1
啊,是的,这取决于所做的更改和打开的文件。为了安全起见,随时可以停止您的Docker引擎。我希望他们在后续版本中添加能够进行更改的功能。没有能力操作重启策略真是太疯狂了。 - hookenz
1
很快可能会添加一个新的集合功能。https://github.com/docker/docker/pull/15078 - hookenz

0

但是这种方法的问题在于,您会失去原始容器中的任何更改,因为您已经将其删除并从头开始创建了一个新容器。我相信,如果原始容器中有需要持久化的更改,那么提交新镜像并从中运行新容器会更好。 - Richard Corfield
所以我们回到了你的提交。 - user2915097
@rdc,你应该尽量避免因为这种原因在容器中进行更改 - 要么将其保留在卷中,要么保存在某种数据库中。 - Adrian Mouat
这个答案已经不再相关,请查看@Frank Wong的答案。 - bluesummers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接