我正在尝试在我的docker容器中运行shell脚本。问题是shell脚本生成另一个进程,它应该继续运行,除非使用另一个关闭脚本来终止由启动脚本生成的进程。
当我运行以下命令时,
docker run image:tag /bin/sh /root/my_script.sh
然后,
docker ps -a
我看到该命令已退出。但这不是我想要的。我的问题是如何让命令在后台运行而不退出?
答案 0 :(得分:6)
您还没有解释为什么要在脚本退出后看到您的容器正在运行,或者您是否期望您的脚本退出。
一旦容器的CMD
退出,docker容器就会退出。如果您希望容器继续运行,则需要一个可以继续运行的进程。一个选项就是在脚本末尾放置一个while循环:
while :; do
sleep 300
done
您的脚本永远不会退出,因此您的容器将继续运行。如果您的容器承载网络服务(Web服务器,数据库服务器等),那么这通常是容器生命周期的运行过程。
如果您的脚本意外退出,您可能需要查看容器日志(docker logs <container>
)并可能在脚本中添加一些调试。
如果您只是问“我如何在后台运行容器?”,那么Emil的回答(将-d
标志传递给docker run
)将帮助您解决问题。
答案 1 :(得分:4)
docker运行的进程取代了UNIX进程树中的init。 init
是最顶层的父进程,一旦退出docker容器就停止。任何子进程(现在都是orphan process)也将被停止。
$ docker pull busybox >/dev/null
$ time docker run --rm busybox sleep 3
real 0m3.852s
user 0m0.179s
sys 0m0.012s
所以你不能允许父pid退出,但你有两个选择。您可以保留父进程并允许它管理其子进程(例如,通过将其告知wait
直到所有子进程都退出)
$ time docker run --rm busybox sh -c 'sleep 3 & wait'
real 0m3.916s
user 0m0.178s
sys 0m0.013s
...或者您可以使用exec
将子进程替换为子进程。这意味着新命令正在父进程的空间中执行......
$ time docker run --rm busybox sh -c 'exec sleep 3'
real 0m3.886s
user 0m0.173s
sys 0m0.010s
后一种方法可能很复杂,具体取决于子进程的性质,但运行较少的不必要的进程更具有惯用的Docker。 (这并不是说你应该只有一个进程。)
答案 2 :(得分:3)
使用您的脚本在后台使用以下命令运行容器
docker run -i -t -d image:tag /bin/sh /root/my_script.sh
通过docker ps
命令
然后验证您的脚本是否正在容器上执行
docker exec <id> /bin/sh -l -c "ps aux"
答案 3 :(得分:1)
使用docker-entrypoint.sh bash脚本包装程序,该脚本阻止容器进程并能够捕获ctrl-c。这个bash示例应该有所帮助: https://rimuhosting.com/knowledgebase/linux/misc/trapping-ctrl-c-in-bash
当Docker发送退出信号时,脚本应该干净地关闭进程。
您还可以在脚本中添加一个循环,重复检查正在运行的进程。