Python inside docker container, gracefully stop

2019-08-07 13:21发布

I'm running a very basic example of Python loop inside a Windows docker container, that I would like to gracefully stop.

The script is started this way in my dockerfile:

CMD [ "python.exe" , "./test.py"]

In the docker documentation it's said a SIGTERM signal is sent to the main command, so I'm trying to catch it this way:

import signal
import time
import logging, sys

class GracefulKiller:
  kill_now = False
  def __init__(self):
    signal.signal(signal.SIGINT, self.exit_gracefully)
    signal.signal(signal.SIGTERM, self.exit_gracefully)

  def exit_gracefully(self,signum, frame):
    self.kill_now = True

if __name__ == '__main__':
  logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
  killer = GracefulKiller()
  while True:
    time.sleep(1)
    logging.info("doing something in a loop ...")
    if killer.kill_now:
      break

  logging.info("End of the program. I was killed gracefully :)")

In theory the signal should be caught by the handler, the boolean should toggle and the loop should exit and display my very last log line. It doesn't, it's just stopping the whole thing at the moment the signal is emitted (or 2-3 seconds later rather)

C:\Users\Administrator\Documents\Projects\test>docker-compose up
Recreating test_1 ... done
Attaching to test_1
test_1  | INFO:root:doing something in a loop ...
test_1  | INFO:root:doing something in a loop ...
test_1  | INFO:root:doing something in a loop ...
test_1  | INFO:root:doing something in a loop ...
test_1  | INFO:root:doing something in a loop ...
test_1  | INFO:root:doing something in a loop ...
test_1  | INFO:root:doing something in a loop ...
test_1  | INFO:root:doing something in a loop ...
test_1  | INFO:root:doing something in a loop ...
test_1  | INFO:root:doing something in a loop ...
test_1  | INFO:root:doing something in a loop ...
test_1  | INFO:root:doing something in a loop ...
test_1  | INFO:root:doing something in a loop ...
test_1  | INFO:root:doing something in a loop ...
Gracefully stopping... (press Ctrl+C again to force)
Stopping test_1   ... done

My last line log is never reached. Does anyone knows what's going on ? Is it a python specific issue, docker specific or Windows specific?

Also I tried to inspect the stopped container with docker logs, the last log isn't here either. Tried to add a sleep after it, same result.

Thanks,

1条回答
爱情/是我丢掉的垃圾
2楼-- · 2019-08-07 13:45

Just catch KeyboardInterrupt and that's it.

if __name__ == '__main__':
  logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
  try:
    while True:
      time.sleep(1)
      logging.info("doing something in a loop ...")
  except KeyboardInterrupt as ex:
    print('goodbye!')
查看更多
登录 后发表回答