当使用docker容器执行周期性任务时,如何保持容器启动

当使用docker容器执行周期性任务时,如何保持容器启动

我有一个已安装并配置好软件的 Docker 容器。

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

我想要的是 - 它能够根据外部事件启动一些命令。例如:

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

docker exec mysupercont /path/to/myothercommand 

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

docker run ...

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

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

答案1

您不需要每次都执行docker run

docker run实际上是两个命令的序列:“create”和“start”。

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

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

例子:

docker run -it debian:stable bash

工作完成后,执行启动时指定的命令(在我的示例中为 bash)。例如,执行“exit”。容器停止:

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容器之间的区别。
此外,看看文档为参数“ ”的作用,为-i t-d”的“运行”

答案2

既然你提到了定期任务,而且你可能因为想要使用 的方式而使用 cron 之类的东西docker exec,那么我就有适合你的药了。至少我最终做了类似的事情。

  1. Dockerfile

    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 可以处理业务逻辑中更奇特的依赖和环境变量。如果您的定期任务卡住并出现内存泄漏等问题,您还可以设置一些限制。

答案3

Tail 仍然会时不时地引发一些文件操作。

永远睡觉,无任何副作用

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

怎么运行的

while :;           # Run an endless loop,
do :;              # of do nothing,
done &             # as background task.
kill -STOP $!      # Stop the background task.
wait $!            # Wait forever, because background task process has been stopped.

答案4

我自己已经使用了这里提出的所有解决方案,但是当 Docker 守护进程想要关闭容器时,它们都无法处理来自 Docker 守护进程的 SIGTERM 信号(例如docker stop $containername)。

因此我建议如下:

FROM base:image
# ...
CMD sh -c 'trap "exit" TERM; while true; do sleep 1; done'

它基本上是一个简短的 shell 脚本,首先拦截(“捕获”)SIGTERM 信号,然后在无限循环中休眠一秒钟。

我主要将它与docker-compose一起使用,奥菲莉亚提供侧车容器来备份另一个容器中的其他服务(例如 MariaDB 数据库)。

相关内容