如何在Docker Compose中配置容器停止时自动执行订阅删除脚本?
问题描述
我有两个bash脚本:
- 第一个
run.sh用于运行Python脚本创建以主机名命名的Google Pub/Sub订阅并监听,已配置在Docker Compose的entrypoint(也试过command)中,脚本内容如下:
#!/bin/sh python -u client.py 'project-id' 'receive' 'topic-name' "subsciber-$(hostname -f)"
Docker Compose配置片段:
services: subscription: .... entrypoint: ["/bin/sh", "/opt/subscription/scripts/run.sh"]
- 第二个
delete-subscriber.sh用于删除该订阅,脚本内容:
#!/bin/sh python -u client.py 'project-id' 'delete' "subscriber-$(hostname -f)"
对应的client.py核心逻辑:
if __name__ == '__main__': args = parser.parse_args() if args.command == 'receive': create_subscription(args.project, args.topic_name, args.subscription_name) receive_messages(args.project, args.subscription_name) elif args.command == 'delete': delete_subscription(args.project, args.subscription_name)
我希望容器停止时自动执行delete-subscriber.sh,除了手动通过docker compose events(stop、kill等)触发外,Docker Compose配置中有没有对应的选项?
解决方案
Docker Compose本身没有直接配置"容器停止时执行脚本"的选项,但可以通过以下方式实现自动触发:
1. 修改entrypoint脚本捕获停止信号
容器的PID 1进程需要正确处理停止信号(如SIGTERM、SIGINT)才能触发清理逻辑。修改run.sh,添加信号捕获和清理函数:
#!/bin/sh # 定义清理逻辑 cleanup() { echo "开始清理,删除Pub/Sub订阅..." /opt/subscription/scripts/delete-subscriber.sh exit 0 } # 捕获停止信号,触发清理 trap cleanup SIGTERM SIGINT # 启动主监听进程并后台运行 python -u client.py 'project-id' 'receive' 'topic-name' "subsciber-$(hostname -f)" & # 等待主进程结束,避免脚本提前退出 wait $!
当容器收到docker compose stop这类停止命令时,trap会触发cleanup函数,自动执行订阅删除操作。
2. 启用Docker init进程转发信号
如果你的Python主进程无法正确处理信号,可以在Docker Compose中添加init: true配置,让Docker内置的tini进程作为PID 1,负责将信号转发给子进程,确保run.sh能捕获到停止信号:
services: subscription: .... entrypoint: ["/bin/sh", "/opt/subscription/scripts/run.sh"] init: true
3. 关键注意事项
- 确保
delete-subscriber.sh有可执行权限,可在Dockerfile中添加:RUN chmod +x /opt/subscription/scripts/*.sh - 若使用
docker compose kill强制杀死容器(发送SIGKILL信号),信号无法被捕获,清理脚本不会执行,这种情况只能依赖外部监控处理 - 测试时优先使用
docker compose stop,该命令发送SIGTERM信号,能正常触发清理逻辑
内容的提问来源于stack exchange,提问作者itx
相关产品推荐
相关产品推荐

