跳转至

优雅停止Docker内Python应用

概要: 本文介绍如何快速优雅地停止运行在Docker容器内部的Python应用

创建时间: 2022.10.27 19:26:38

更新时间: 2023.07.28 22:55:27

Docker容器如何停止

根据Docker官方文档,在执行 docker stop 命令时,Docker容器内的主进程会接收到 SIGTERM 信号,在大概10秒后,如果容器内应用还没有停掉,那么会使用 SIGKILL 信号杀死容器内的应用。

提示

docker compose down 同样停掉Docker容器的原理与 docker stop 一致

Python中的系统信号处理

Python标准库中,有专门用于处理系统信号的 signal 模块,使用 signal.signal() 可以将接收到的信号与自定义的方法或异常绑定。比如将系统的 SIGTERMKeyboardInterrupt 异常绑定,示例如下

Python
1
2
3
4
5
6
import signal

def handle_sigterm(*args):
    raise KeyboardInterrupt()

signal.signal(signal.SIGTERM, handle_sigterm)
此时如果对此进程进行 kill -15 PID(PythonAPP) 操作,则会触发上面自定义的PythonKeyboardInterrupt 异常,*nix 系统的 kill 指令手册如下
image.png
与之对应,Python标准库 signal 可以处理的信号有
image.png

处理Docker容器停止时的信号

有了上面的内容,如果要让容器内的Python应用在接收到Docker容器停止的信号,只需要将 SIGTERM 与Python的自定义异常绑定即可,容器内Python应用主线程示例如下

Python
import signal
import sys


def handle_sigterm(*args):
    raise KeyboardInterrupt()


if __name__ == "__main__":
    try:
        signal.signal(signal.SIGTERM, handle_sigterm)
        run_my_app()
    except KeyboardInterrupt:
        sys.exit(0)

注意

如果程序中除了主线程之外,还使用threading模块创建了线程,那么创建线程时,需要增加参数daemon=True,否则将会导致程序无法正常优雅退出。

参考