在 Docker 的后台测试无限循环?

在 Docker 的后台测试无限循环?

我想在我的 docker 镜像中运行一个后台队列:

php artisan queue:work --daemon --sleep=1 --tries=3 &

之后它立即启动httpd运行 PHPlaravel应用程序的 Apache。该laravel应用程序将推送通知发送到 Redis。后台队列工作程序从 Redis 收集消息并通过推送服务发送它们。

这有效并且每秒都会注销。如果后台命令崩溃,我希望它重新启动。根据这个答案https://unix.stackexchange.com/a/223780/72040我可以在后台无限运行命令,如下所示:

while true; do php $QUEUE_WORK; done &

为了测试这一点,我运行了我的容器,docker run然后docker exec -it登录并查看:

UID        PID  PPID  C STIME TTY          TIME CMD
100000       1     0  0 19:55 ?        00:00:00 httpd -D FOREGROUND
100000      21     1  0 19:55 ?        00:00:00 /bin/sh -e /tmp/scripts/run
100000      22    21  1 19:55 ?        00:00:01 php artisan queue:work --sleep=1 --tries=3
100000      43     1  0 19:55 ?        00:00:00 /usr/bin/cat
100000      50     1  0 19:55 ?        00:00:00 /usr/bin/cat
100000      51     1  0 19:55 ?        00:00:00 /usr/bin/cat
100000      52     1  0 19:55 ?        00:00:00 /usr/bin/cat
100000      53     1  0 19:55 ?        00:00:00 httpd -D FOREGROUND
...
100000     130     0  1 19:57 pts/0    00:00:00 /bin/bash
100000     144   130  0 19:57 pts/0    00:00:00 ps -efww

然后我运行kill 22查看输出docker run

/tmp/scripts/run: line 10:    22 Killed                  php $QUEUE_WORK

循环不会使进程保持运行。我已经仔细检查循环是否是图像中运行的代码。如果我让循环运行“echo x: sleep 1”,它就可以正常运行。

当我杀死它时,为什么循环没有替换命令?

笔记:该应用程序在 Kubernetes 上部署为多个 Pod,并在httpd运行状况检查 URL 返回错误或超时时进行监控和自动重新启动。

我不想将队列工作人员部署为单独的 pod 或 sidecar 容器,我想将其作为容器中的后台进程运行,httpd以便它httpd以零配置共享应用程序代码。

我对运行进程监视器或其他工具或技术来“保持活力”不感兴趣。

我的问题是为什么 Bash 循环会退出kill它正在运行的进程?

答案1

设置

我设置了以下内容Dockerfile

$ more Dockerfile
From centos
ADD run.sh /tmp/run.sh
RUN chmod +x /tmp/run.sh
ENTRYPOINT ["/tmp/run.sh"]

设置脚本,run.sh

$ cat run.sh
while true; do sleep 15 ; echo "background"; done &

while true; do sleep 12 ; echo "foreground"; done

建造它:

$ docker build -t sleeper .
Sending build context to Docker daemon 7.791 MB
Step 1/4 : FROM centos
 ---> 49f7960eb7e4
Step 2/4 : ADD run.sh /tmp/run.sh
 ---> b4099de53780
Removing intermediate container 1ce8e3a1dac5
Step 3/4 : RUN chmod +x /tmp/run.sh
 ---> Running in e410429a6cba

 ---> 06789467e636
Removing intermediate container e410429a6cba
Step 4/4 : ENTRYPOINT /tmp/run.sh
 ---> Running in ad8b847b505f
 ---> a2415df63f99
Removing intermediate container ad8b847b505f
Successfully built a2415df63f99

例子

然后启动它:

$ docker run -dit sleeper
28c19c338e6e6177529cf989f42c7f14b17f1c705a61f5244d5350f0ab8f8364

然后它重复运行并显示:

foreground 
background 
foreground 
background

现在,当我观看它时,我可以看到它仍在运行,尽管sleep命令最终“死亡”:

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS               NAMES
28c19c338e6e        sleeper             "/tmp/run.sh"       About a minute ago   Up About a minute                       focused_lumiere

从上面我们可以看到这个容器已经启动超过1分钟了。这是ps auxf容器内部的样子:

$ ps auxf
...
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root        24  0.0  0.1  11828  2964 pts/1    Ss   16:00   0:00 /bin/bash
root        58  0.0  0.1  51712  3432 pts/1    R+   16:01   0:00  \_ ps auxf
root         1  0.0  0.1  11692  2572 pts/0    Ss+  15:58   0:00 /bin/bash /tmp/
root         5  0.0  0.1  11696  2272 pts/0    S+   15:58   0:00 /bin/bash /tmp/
root        56  0.0  0.0   4368   636 pts/0    S+   16:01   0:00  \_ sleep 15
root        57  0.0  0.0   4368   664 pts/0    S+   16:01   0:00 sleep 12

sleep 15现在,如果我们像这样取消背景:

$ kill 56

并运行另一个docker ps

$ docker ps
...
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root        24  0.0  0.1  11828  2964 pts/1    Ss   16:00   0:00 /bin/bash
root        60  0.0  0.1  51712  3344 pts/1    R+   16:01   0:00  \_ ps auxf
root         1  0.0  0.1  11692  2572 pts/0    Ss+  15:58   0:00 /bin/bash /tmp/
root         5  0.0  0.1  11696  2272 pts/0    S+   15:58   0:00 /bin/bash /tmp/
root        59  0.0  0.0   4368   636 pts/0    S+   16:01   0:00  \_ sleep 15
root        57  0.0  0.0   4368   664 pts/0    S+   16:01   0:00 sleep 12

我们可以看到保护后台进程的 while 循环sleep 15已经完成了它的工作并重新启动了另一个sleep 15.

相关内容