在我的 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 的。或者您可以设置相同的。因此在执行时使用,而仅在构建映像时使用。command
CMD
CMD
CMD
RUN
为了制作出最优质的应用,你必须将任务放入另一个容器中。例如,将其放入 init 容器、使用CronJob
或Job
类似容器中。
当然,无论使用哪种编程语言,任务仍然可以在后台执行。
但具体来说,壳牌需要做出特殊的努力。
这是奖励部分
我仅在 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 解决方案将它们全部放在一起。