what does it actually mean when docker-compose says it is "gracefully stopping "?
Basically when you do Ctrl+C you are sending a SIGINT (2) signal to the application that runs in the foreground. Most of the time, the semantics of this signal is similar to the SIGTERM (15) signal that is raised when doing docker-compose stop
or more basically docker stop
if you are focusing on a single-container application.
Is docker-compose trying some shutdown protocol and then killing my container only after a timeout?
Yes, the idea is that the running application can catch the SIGINT and SIGTERM signal and perform some cleanup operation before exiting.
On the contrary, the SIGKILL (9) signal (raised by docker kill
for example) causes the process to terminate immediately.
You might be interested in this related SO answer where I give a toy example of entrypoint bash script that "catches" SIGINT and SIGTERM signals (but not SIGKILL, of course).
Is there anything I can do to speed up container shutdown when killed via ctrl+c within docker-compose up?
I'd say the time spent by your containers to exit when you do docker stop
or so strongly depends on the implementation of the corresponding images.
At first sight, you might modify (e.g., shorten) the time offered to the containers to gracefully stop:
docker stop -t TIMEOUT
(doc)
docker-compose stop -t TIMEOUT
(doc)
but this would certainly not be a proper solution.
Actually, there are two typical pitfalls when one comes to rely on an entrypoint bash script:
Use a bash script as a wrapper to finally call another program, but forget to use the exec
builtin.
→ The recommended practice consists in prepending the last command of a bash entrypoint with exec
(for example, see this line from entrypointd.sh
in sudo-bmitch/docker-base
).
When the bash script itself should not terminate immediately, one could forget to take care of trapping the signals (including SIGINT and SIGTERM) and behave accordingly, which can also be the cause of the issue you observe. This is related to the so-called PID 1 zombie reaping problem.
→ To workaround this, you may want to run your image with the docker run
flag --init
, or add the docker-compose.yml
parameter init
(related SO Q.)
nodejs
containers, but until now I haven't found out why. It seems like eithertrap 'exit 1' TERM INT
orexec
is missing in theENTRYPOINT
+CMD
chain, but I cant exactly say (otherwise I'd have fixed it by now) This "quickfix" does the trick for me. – Integument