docker-compose up时指定command不执行,进入容器手动运行正常如何排查
问题根本原因
你的my_script.sh中两个rq worker进程都通过&放入后台执行,脚本执行完这两行命令后就会直接终止。而Docker容器的生命周期与command指定的主进程完全绑定,主进程退出后容器会立刻停止运行,因此worker进程刚启动就随容器终止了,看起来就像脚本没有执行。
你手动进入容器执行脚本可以成功,是因为此时容器的主进程是tail -f /dev/null,会一直保持运行不退出,后台的worker进程自然可以正常运行。
排查验证方向
- 执行
docker ps -a查看my_service对应容器的状态,如果STATUS列为Exited,即可验证主进程运行结束后容器正常退出的判断 - 给脚本添加调试日志确认执行情况:修改
my_script.sh,在首尾添加日志输出命令,示例如下:
容器退出后执行# my_script.sh echo "$(date): 脚本开始执行" >> /tmp/run.log rq worker worker_1 & echo "$(date): worker_1已启动" >> /tmp/run.log rq worker worker_2 & echo "$(date): worker_2已启动" >> /tmp/run.log echo "$(date): 脚本执行完成" >> /tmp/run.logdocker cp my_service_1:/tmp/run.log .即可将日志拷贝到宿主机查看,确认脚本是否已经正常执行。
可行解决方案
方案1:修改脚本保持主进程不退出
在脚本末尾添加阻塞命令,避免主进程提前退出:
# my_script.sh rq worker worker_1 & rq worker worker_2 & # 等待所有后台子进程运行,只要有一个worker存活,主进程就不会退出 wait
也可在末尾添加tail -f /dev/null实现同样的阻塞效果。
方案2:使用进程管理工具托管worker
使用supervisor等进程管理工具作为容器主进程,托管两个rq worker进程,不仅可以保持容器运行,还能实现worker异常自动重启,更适合生产环境使用。
方案3:拆分为独立service
如果没有特殊要求必须放在同一个容器,可以在docker-compose.yml中拆分为两个独立的service,每个service直接运行rq worker worker_x命令,不需要后台运行,也不需要额外的启动脚本。
内容的提问来源于stack exchange,提问作者JSB
相关产品推荐
相关产品推荐

