在 Docker 容器内运行后台脚本

在 Docker 容器内运行后台脚本

在我的 Dockerfile 中,我运行一个脚本:

RUN /bin/sh -c scripts/init.sh

在 中init.sh,所有以 结尾的命令&都不会执行:我无法运行后台进程。知道原因吗?

答案1

我遇到了类似的问题,下面的内容对我有帮助。

RUN nohup bash -c "scripts/init.sh &" && sleep 4

在许多情况下,您启动的服务器尚未完全准备就绪。为了让服务器有更多时间准备就绪,请添加 sleep 命令。参数 sleep 的大小取决于您启动的服务,您可能需要对其进行调整。

阅读更多在此文档上

答案2

使用 docker RUN 命令在后台运行命令似乎不起作用的原因是 RUN 发生在 docker 构建时。这些命令有助于构建 docker 镜像,例如安装 docker 实例化时需要的内容,或设置在 docker 实例化时将使用的配置文件。在构建时在后台运行命令毫无意义。

答案3

要在后台运行某些程序,让我们在 Dockerfile 中使用它:

FROM ubuntu:20.04
RUN mkdir /scripts
RUN echo 'touch /tmp/file &' >> /scripts/init.sh
RUN echo 'tail -F /dev/null' >> /scripts/init.sh
CMD sh -c "sh /scripts/init.sh"

您可以tail -F /dev/null用下一个不会退出并保持容器运行的命令/服务进行替换。

构建和测试:

docker build -t mytest .
docker run -td --name mytest mytest
docker exec mytest ls -l /tmp/file

请注意,不应在 Docker Compose、Kubernetes 或任何容器管理/编排工具中设置entrypoint和。它们会覆盖 Dockerfile 的。或者您可以设置相同的。因此在执行时使用,而仅在构建映像时使用。commandCMDCMDCMDRUN


为了制作出最优质的应用,你必须将任务放入另一个容器中。例如,将其放入 init 容器、使用CronJobJob类似容器中。

当然,无论使用哪种编程语言,任务仍然可以在后台执行。

但具体来说,壳牌需要做出特殊的努力。


这是奖励部分

我仅在 Ubuntu 上测试过这一点,使用 Shell 和 Docker 进行线程记录。

尝试在另一个步骤之后添加此步骤touch

RUN echo 'touch /proc/no_file_can_be_created_in_proc_dir > /proc/1/fd/1 >> /proc/1/fd/2 &' >> /scripts/init.sh

因此它会打印该后台任务的日志:

$ docker logs mytest
touch: cannot touch '/proc/no_file_can_be_created_in_proc_dir': No such file or directory

因此,诀窍是在命令中使用> /proc/1/fd/1 >> /proc/1/fd/2 &而不是仅仅使用。&

答案4

我的第一个想法是在容器内创建服务,而不是用nohup或运行它们&,将它们作为系统服务运行,并且不需要在 init.sh 中处理它们。

但这不是“真正的”docker 方法。如果您需要运行多个服务,请将它们分离到不同的容器中(1 个容器 - 1 个服务),然后使用 docker-compose 解决方案将它们全部放在一起。

相关内容