'Speed up docker-compose shutdown

When I set up my application to run via docker-compose up, it takes several seconds to stop on ctrl+c. However, if I run docker kill ..., the container stops very quickly. Is there anything I can do to speed up container shutdown when killed via ctrl+c within docker-compose up?

In particular, what does it actually mean when docker-compose says it is "gracefully stopping "? Is docker-compose trying some shutdown protocol and then killing my container only after a timeout?



Solution 1:[1]

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:

  1. 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).

  2. 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.)

Solution 2:[2]

If you find yourself restarting containers frequently and some don't gracefully exit or have long exit times (ie. you want more than 10s before it's killed), you can now do this per-service/container with stop_grace_period

stop_grace_period specifies how long the Compose implementation MUST wait when attempting to stop a container if it doesn’t handle SIGTERM (or whichever stop signal has been specified with stop_signal), before sending SIGKILL. Specified as a duration.

For example

services:
  service_A:
    ...
    stop_grace_period: 1s  # SIGKILL after 1s
  service_B:
    ...
    stop_grace_period: 5m30s  # wait a long time before SIGKILL

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 ti7