How can I stop a docker container running sleep?
Solution 1:
When you run docker stop ...
, some things will happen:
-
docker
sends aSIGTERM
to the main process of the container. The process is able to mask/ignore aSIGTERM
, and if it does so (or handles it without terminating) "nothing" will happen. - After a timeout (default 10 seconds),
docker
sends aSIGKILL
to the main process. This signal cannot be masked by a process, and thus it dies immediately with no opportunity for executing a shutdown prodedure.
Ideally, processes run within docker
will respond to the SIGTERM
in a timely fashion, taking care of any housekeeping before terminating.
If you know that the process either doesn't have any housekeeping to perform (e.g: sleep
), or will not respond properly to SIGTERM
, you can specify a shorter (or longer) timeout with the -t
flag:
-t, --time=10 Seconds to wait for stop before killing it
For example, in your case, you may like to run docker stop -t 0 ${CONTAINER}
.
The reason that this signal behaviour is different is due to the sleep
running with PID = 1.
Typically (e.g: running with PID != 1), any signal that the process doesn't explicitly deal with leads to the process being terminated - try sending a sleep
a SIGUSR1
.
However, when running with PID = 1, unhandled signals are ignored, otherwise you'd end up with a kernel panic:
Kernel panic - not syncing: Attempted to kill init!
You can send a signal to the docker container using docker tools, for example:
docker kill -s TERM kill-sleep
As we can see, this doesn't have the desired effect, whereas this does:
docker kill -s KILL kill-sleep
An Experiment
Dockerfile
FROM busybox
COPY run.sh /run.sh
RUN chmod +x /run.sh
CMD "/run.sh"
run.sh
#!/bin/sh
echo "sleeping"
sleep 100000
Now, run
docker build -t kill-sleep .
docker run --rm --name kill-sleep kill-sleep
And this in a different terminal:
docker stop kill-sleep
We observe the same 10 second delay / timeout.
A Solution
Now let's handle the SIGTERM
. Backgrounding and wait
ing for sleep
are due to how a POSIX shell handles signals (see this for more).
run.sh
#!/bin/sh
die_func() {
echo "oh no"
sleep 2
exit 1
}
trap die_func TERM
echo "sleeping"
sleep 100000 &
wait
Run the commands again, and we see what we are after!
$ time docker stop kill-sleep
kill-sleep
real 0m2.515s
user 0m0.008s
sys 0m0.044s