优雅地停止Docker容器

我有一些麻烦了解如何我可以做一些清理当容器停止。

为了更容易,我准备了一个样本来重现问题。

这里是我的文件的内容:

Dockerfile

FROM opensuse:latest # Install tcsh (non-interactive mode) RUN zypper -n in tcsh # Create user RUN useradd -ms /bin/tcsh dummyuser # Set the user USER dummyuser # Change Working Dir WORKDIR /home/dummyuser # Copy entrypoint script COPY docker-entrypoint.sh $HOME # Starter Script ENTRYPOINT ["./docker-entrypoint.sh"] 

docker-entrypoint.sh

 #!/bin/tcsh echo "Starting" onintr cleanup # Running something in foreground, otherwise the container will stop while (1) sleep 1000 end exit 0 cleanup: onintr - echo "cleanup on going" exit 0 

使docker-entrypoint.sh可执行文件:

 chmod 744 docker-entrypoint.sh 

build立图像:

 docker build -t my-dummy-img . 

注意我正在使用tcsh shell。

如果你看看docker-entrypoint.sh你可以看到我正在等待中断( onintr cleanup )并调用清理方法。

现在,这些是我运行的命令:

 mstack/dummy-project> docker run --name my-service -ti -d my-dummy-img ps -eaf da1dc21281a58e384f2ff34aa49a82019214e204e6d7a77ff54e8c96e005f913 mstack/dummy-project> docker logs my-service Starting mstack/dummy-project> docker stop my-service my-service mstack/dummy-project> docker logs my-service Starting mstack/dummy-project> 

这是问题,我期望第二个docker logs my-service后输出将是:

 Starting cleanup on going 

而不是只有

 Starting 

因为docker应该停止时发送一个信号…

另一方面,如果我运行:

docker run --name my-service-attached -ti my-dummy-img ps -eaf

并按CTRL+C ,我可以看到预期的输出。

我在这里错过了什么? 我希望这个问题很清楚。

顺便说一句,我用下面的文章作为指导:

优雅地停止Docker容器

在Docker容器中捕获信号

这可能是因为您以分离模式启动它: 请参阅文档 。

如果shell运行分离,则忽略onintr

你将不得不寻找替代scheme,就像在这里看到的使用bash和陷阱一样

终于解决了这个问题。

Tcsh shell不会收到大部分信号,如停靠容器时Docker发送的信号SIGTERM 。

所以我改变脚本使用bash shell,每当我想运行一个tcsh命令,我只是这样做:

 /bin/tcsh ./my-command 

所以,我的docker-entrypoint.sh是这样的:

 #!/bin/bash # SIGTERM-handler this funciton will be executed when the container receives the SIGTERM signal (when stopping) term_handler(){ echo "***Stopping" /bin/tcsh ./my-cleanup-command exit 0 } # Setup signal handlers trap 'term_handler' SIGTERM echo "***Starting" /bin/tcsh ./my-command # Running something in foreground, otherwise the container will stop while true do #sleep 1000 - Doesn't work with sleep. Not sure why. tail -f /dev/null & wait ${!} done