尽pipe有`-t 120`的设置,Docker几乎立即停止closures容器

这是我如何build立docker图像:

docker build -f Dockerfile -t python-trapterm . 

这是我如何运行它:

  docker run -t python-trapterm:latest 

我试图阻止它

  docker stop -t 120 sharp_jones 

我预计在容器closures之前有2分钟的运行时间。 但它几乎立即closures? 为什么?

这是来自容器进程的输出:

 > docker run -t python-trapterm:latest Setting traps... * Starting NTP server ntpd [ OK ] 2017-09-10 06:43:02,501 pid 26 tid 140693944227584 INFO greatapp Registering signal handler 2017-09-10 06:43:02,502 pid 26 tid 140693944227584 INFO greatapp Hello! 2017-09-10 06:43:04,507 pid 26 tid 140693944227584 INFO greatapp Checking every 2s... 2017-09-10 06:43:06,510 pid 26 tid 140693944227584 INFO greatapp Checking every 2s... 2017-09-10 06:43:08,512 pid 26 tid 140693944227584 INFO greatapp Checking every 2s... [snip] 2017-09-10 06:44:12,629 pid 26 tid 140693944227584 INFO greatapp Checking every 2s... 2017-09-10 06:44:14,631 pid 26 tid 140693944227584 INFO greatapp Checking every 2s... Sending term to 26... 2017-09-10 06:44:16,537 pid 26 tid 140693944227584 INFO greatapp Handling shutdown...15 2017-09-10 06:44:16,538 pid 26 tid 140693944227584 INFO greatapp Checking every 2s... 2017-09-10 06:44:16,539 pid 26 tid 140693944227584 INFO greatapp Handling shutdown...10 2017-09-10 06:44:16,539 pid 26 tid 140693944227584 INFO greatapp Checking every 2s... 

您可以看到TERM信号在06:44:16左右收到,但工作已经在06:44:14左右closures,但是过程在06:44:16之后终止。 没有10秒钟的等待。

这是我的docker文件:

 FROM ubuntu:16.04 RUN apt-get update --fix-missing && apt-get install -y \ git \ python \ python-pip \ ntp \ curl vim screen lsof RUN mkdir -p /app COPY ./app /app CMD ["/app/start-app.sh"] 

这是我的app目录中的两个文件:

应用程序/ start-app.sh

 #!/bin/bash set -eo pipefail echo "Setting traps..." trap 'cleanup_term' TERM trap 'cleanup_kill' KILL cleanup_term() { echo "Sending term to `jobs -p`..." kill -TERM `jobs -p` kill -USR1 `jobs -p` } cleanup_kill() { echo "Received kill..." kill -TERM `jobs -p` } service ntp start cd /app python -m greatapp & wait 

应用程序/ greatapp.py

 import os import time import logging import signal LOG_FORMAT = "%(asctime)-15s pid %(process)d tid %(thread)4d %(levelname)-8s" \ " %(module)-8s %(message)s" logging.basicConfig(format=LOG_FORMAT) LOG = logging.getLogger(__file__) LOG.setLevel(logging.DEBUG) def docker_shutdown_handler(_signum, _frame): LOG.info("Handling shutdown...%s", _signum) # sys.exit() LOG.info('Registering signal handler') signal.signal(signal.SIGTERM, docker_shutdown_handler) signal.signal(signal.SIGUSR1, docker_shutdown_handler) def main(): LOG.info("Hello!") sleep_time = 2 while True: time.sleep(sleep_time) LOG.info("Checking every %ds...", sleep_time) if __name__ == '__main__': main() 

你的shell脚本正在退出。 当发生这种情况时,由于它是pid 1,容器立即退出。 如果将以下内容添加到脚本的顶部,您可以看到这一点:

 trap 'echo Script exiting' EXIT 

这很可能是bash中SIGKILL的默认操作,因为在最后一次等待之后它没有运行任何命令。 快速的解决方法是给清理函数添加一个等待,以便信号处理程序挂起:

 cleanup_term() { echo "Sending term to `jobs -p`..." kill -TERM `jobs -p` kill -USR1 `jobs -p` echo "waiting again" wait echo "cleanup_term done" } 

或者我build议只执行Python脚本,以便直接处理信号,并消除pid 1中的bash。然后,start-app.sh将如下所示:

 #!/bin/bash set -eo pipefail service ntp start cd /app exec python -m greatapp