在用于定期任务时保持Docker容器启动的正确方法


41

我有安装和配置软件的Docker容器。

没有任何程序应该一直启动/运行。

我想要的-根据外部事件启动某些命令的能力。喜欢:

docker exec mysupercont /path/to/mycommand -bla -for

docker exec mysupercont /path/to/myothercommand 

但是当容器停止时“执行”是不可能的,而且这个容器内部有一些“工作”数据,这些数据用于该命令,所以我不能使用

docker run ...

每次,因为它从图像重新创建了容器并破坏了我的数据。

保持此类容器运行的“正确”和“最佳”方法是什么?我可以在里面启动哪个命令?


这是一个很好解释的问题。在这里看到另一个类似的帖子。
Grant Li

1
docker run -d --name=name container tail -f /dev/null
蒸汽动力

Answers:


46

您无需每次都执行docker run

docker run 实际上是两个命令的序列:“创建”和“启动”。

运行容器时,必须指定“ -it”:

-i,--
interactive = false 即使未连接也保持STDIN打开-t,--tty = false分配伪TTY

例:

docker run -it debian:stable bash

工作完成后,在启动时指定命令(在我的示例中为bash)。例如,您执行“退出”。集装箱停靠站:

CONTAINER ID        IMAGE                      COMMAND                CREATED             STATUS                     PORTS               NAMES
1329c99a831b        debian:stable              "bash"                 51 seconds ago      Exited (0) 1 seconds ago                       goofy_bardeen

现在您可以重新启动

docker start 1329c99a831b

启动容器,然后再次执行命令“ bash”。
使用命令连接到该会话“ bash”

docker attach 1329c99a831b

总结:您必须了解runstart容器之间的区别。
此外,请参阅文档,了解“ Run” 参数“ -i t”和“ -d” 的作用


1
啊哈,我明白这一点。问题是:我没有什么可以在容器中运行的,但是我需要将其保持在“运行”状态,所以您的答案是-使用bash使容器保持在运行状态?
Korjavin Ivan

是的。您在运行时指定的进程必须正在容器中运行才能继续工作。最简单的例子是bash。也许您将是使用“ -d”启动容器并根据需要使用进行连接的最简单方法docker attach ID。退出本次会议而无需结束bash,可以使用CTRL-p CTRL-q
MSemochkin 2015年

您在容器运行期间指定的过程将收到
PID1

我对启动和附加(或以-ai开头)的经验是,命令行的提示和交互式编辑没有显示。例如,tty不会渲染或回显。
dlamblin

1
这很漂亮。请注意,如果您想在后台启动容器而不必手动再次启动它(例如,如果您正在运行Web服务),请使用'-itd'参数,并使用CTRL-p CTRL-q来分离而不停止容器。
taranaki '17

6

是否可以启动已停止的容器的整个过程取决于容器最初是如何创建(即运行)的。如果运行的命令已结束,或者退出了交互式命令(例如bash),则无法启动,重新启动或执行已停止的容器。您所能做的就是将其删除。是垃圾

但是taranaki的最后一条评论使用'-itd',似乎是码头工人命令的。

容器保持运行状态,您可以执行所需的任何操作,也可以停止,启动或重新启动容器。当然,这只是基于高山图像的初步发现。请注意,如果您附加到容器,则退出时容器将停止,但是您可以再次启动它。


2
+1“似乎是码头工人的命令” :-)
马特·亚历山大

5

由于您提到了定期任务,并且由于您想使用的方式,您可能正在使用cron之类的东西docker exec,所以我为您准备了药物。至少我最终做了这样的事情。

  1. Docker文件

    FROM <some base>
    CMD tail -f /dev/null
    
  2. 用通常的方式运行docker run -d ....(我用过docker-compose

  3. 设置主机crontab,例如:

    * * * * * docker exec mysupercont foo >> /var/log/foo.log 2>&1
    * * * * * docker exec mysupercont bar >> /var/log/bar.log 2>&1
    

我发现这个解决方案很好,因为我们可以在一个相当漂亮的默认Linux环境中依赖古老而久经考验的crontab,而Docker则可以处理您的业务逻辑中更为奇特的deps和环境变量。如果您的定期任务卡住,内存泄漏或其他原因,您还可以设置一些限制。


0

尾部仍会不时引起一些文件操作。

这是我永远睡眠的解决方案,没有任何副作用。

# Ah, ha, ha, ha, stayin' alive...
while true; do :; done & kill -STOP $! && wait $!

这个怎么运作

while true; do :; done & # do nothing(:) in background, in an endless loop
kill -STOP $!            # stop the background process of doing nothing
wait $!                  # wait forever, because doing nothing process is stopped

1
很难理解它在做什么。为什么不睡觉3650d
Pieter,

1
没错,睡眠可能和我的解决方案一样好,但是睡眠最终会超时:-D PS:我将添加一些评论,以使我的解决方案易于理解。
qoomon
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.